第一部分 基础
一、请描述java语言的反射机制作用
Java反射机制主要提供了以下功能: 在运行时判断任意一个对象所属的类; 在运行时构造任意一个类的对象; 在运行时判断任意一个类所具有的成员变量和方法;在运行时调用任意一个对象的方法;生成动态代理。
二、单例模式
1、懒汉械
public class SingLeton {
private static SingLeton singLeton = null;
private SingLeton() {
//readConfig();
}
public static SingLeton getSingLeton() {
if (singLeton == null) {
singLeton = new SingLeton();
}
return singLeton;
}
……
}
2、饿汉模式
public class SingLeton {
private static SingLeton singLeton = new SingLeton();
private SingLeton() {
//readConfig();
}
public static SingLeton getSingLeton() {
return singLeton;
}
……
}
两种模式区别在于,懒汉模式是在需要时,才实例化;而饿汉模式是在加载时实例化。
饿汉式是线程安全的,因为虚拟机保证了只会装载一次,在装载类的时候是不会发生并发的。 懒汉式是非线程安全,要实现线程安全,加 "synchronized";public static synchronized Singleton getInstance(){}
懒汉式是典型的时间换空间; 饿汉式是典型的空间换时间
三、代理模式
java.lang.reflect.Proxy:这是 Java 动态代理机制的主类,它提供了一组静态方法来为一组接口动态地生成代理类及其对象。
清单 1. Proxy 的静态方法
// 方法 1: 该方法用于获取指定代理对象所关联的调用处理器
static InvocationHandler getInvocationHandler(Object proxy)
// 方法 2:该方法用于获取关联于指定类装载器和一组接口的动态代理类的类对象 static Class getProxyClass(ClassLoader loader, Class[] interfaces)
// 方法 3:该方法用于判断指定类对象是否是一个动态代理类
static boolean isProxyClass(Class cl)
// 方法 4:该方法用于为指定类装载器、一组接口及调用处理器生成动态代理类实例 static Object newProxyInstance(ClassLoader loader, Class[] interfaces,
InvocationHandler h)
java.lang.reflect.InvocationHandler:这是调用处理器接口,它自定义了一个 invoke 方法,用于集中处理在动态代理类对象上的方法调用,通常在该方法中实现对委托类的代理访问。 例:
public class HelloWorldHandler implements InvocationHandler{
private Object obj;
public HelloWorldHandler(Object obj){
this.obj = obj;
};
public Object invoke(Object arg0, Method arg1, Object[] arg2) throws Throwable {
Object result;
doBefore();
result = arg1.invoke(this.obj, arg2);
doAfter();
return result;
}
private void doBefore() {
}
private void doAfter() {
}
}
public static void main(String[] args) {
HelloWorld hw = new HelloWorldImpl();
InvocationHandler handler = new HelloWorldHandler(hw);
HelloWorld proxy = (HelloWorld)
Proxy.newProxyInstance(hw.getClass().getClassLoader(),
hw.getClass().getInterfaces(),handler);
proxy.sayHelloWorld();
}
四、工厂模式
例
public static Car getCarInstance(String type){
Car c=null;
if("Benz".equals(type)){
c=new Benz();
}
if("Ford".equals(type)){
c=new Ford();
}
return c;
}
public static void main(String[] args) {
Car c = Factory.getCarInstance("Ford");
if (c != null) {
c.run();
c.stop();
} else {
System.out.println("造不了这种汽车。。。");
}
}
第二部分 hibernate
一、数据缓存策略
ORM数据缓存:事物级缓存;应用级/进程级缓存;分布式缓存三种。
二、hibernate数据缓存分为两种:
三、Hibernate提供的第三方缓存接口有:JCS,EHCache,OSCache,JBoss Cache,SwarmCache
四、hibernate锁(Locking):
1、悲观锁:基于数据库锁的机制时现。 数据库表现:对数据库表进行锁定(for update)。 hibernate hql表现为:query.setLockMode("锁定对象", LockMode.update); 1、内部缓存(Session level,称为一级缓存) 2、二级缓存(SessionFactory level,称为二级缓存) 2、乐观锁:基于数据库版本记录机制实现。即,为数据增加一个版本标实,通过为数据库表增加一个"version"字段来实现。读取数据时,将版本号一同读出,做更新时加1,提交数据库时,与数据 库版本后进行对本,如何提交数据版本号大于数据库实际版本号,则进行更新。否则认为数据过期。
五、hibernate数据加载:
Session load/get:方法可以根据实体类和ID从数据库读取记录,并返加与之对应的实体对象。 区别:1、未找到记录时,get返回null。load返回是的ObjectNotFoundException; 2、load返回的是一个对象代理实例。get方法直接返回对象实例; 3、load可利用内部缓存和二级缓存(如果内部缓存没有数据,则到二级缓存查找)。而get只能应用内部缓存(如果,内部缓存没有数据,则直接调用sql查询)。
六、Hibernate中Session.find/iterator:
Session.find/iterator:都是根据条件,从数据库获取符合条件的记录。 区别:find查询一次(本将查询记录直接构建成对象,纳入缓存);而iterator要分1+n(满足条件数据数)次查询
七、Hibernate2延迟加载主要针对:实体对象、集合。 hibernate3提供的对属性的延迟加载。 hibernate2 lazy默认为false;hibernate默认为true。
八、hibernate中session与sessionfactory的联系,分别什么时候用
sessionFactory、session都是由hibernate框架生成的,其中sessionFactory包括了数据库配置和映射关系等资源,一个项目中只能生成一个sessionFactory实例。因此sessionFactory被设计成线程安全的。session是对对象进行操作并映射至对应的数据库表中的,它由sessionFactory生成,不支持多线程并发,因此它是非线程安全的。
九、hibernate与iBATIS的区别
hibernate和ibatis都是持久层的ORM框架,hibernate是全自动化的,而ibatis是半自动化的。
为什么这样说呢?因为hibernate把我们要用到的增、删、改的SQL语句都封装了,我们不需要再自己手动写,直接调用即可, 所以称它全自动。而对于ibatis,所有的SQL语句都要我们自己来手写,所以称它为半自动化的框架,就等于是一个O/R Mapping 解决方案.有了这框架,只要配置下映射文件,就不需要手写sql语句了.Hibernate是全自动化的,可以说O/R做的相当全面了.
iBateis和Hibernate相比,iBatis最大的特点就是小巧,上手很快。如果你不需要太多复杂的功能,iBatis是能满足你的要求又足 够灵活的最简单的解决方案
十、hibernate的优化(项目)
1.使用双向一对多关联,不使用单向一对多
2.灵活使用单向一对多关联
3.不用一对一,用多对一取代
4.配置对象缓存,不使用集合缓存
5.一对多集合使用Bag,多对多集合使用Set
6. 继承类使用显式多态
7. 表字段要少,表关联不要怕多,有二级缓存撑腰
十一、hibernate中session与sessionfactory的联系,分别什么时候用
sessionFactory、session都是由hibernate框架生成的,其中sessionFactory包括了数据库配置和映射关系等资源,一个项目中只能生成一个sessionFactory实例。因此sessionFactory被设计成线程安全的。session是对对象进行操作并映射至对应的数据库表中的,它由sessionFactory生成,不支持多线程并发,因此它是非线程安全的。
十二、在项目中用hibernate ORM框架与传统jdbc比较有什么优点
延迟加载:
延迟加载机制是为了避免一些无谓的性能开销而提出来的,所谓延迟加载就是当在真正需要数据的时候,才真正执行数据加载操作。在Hibernate中提供了对实体对象的延迟加载以及对集合的延迟加载,另外在Hibernate3中还提供了对属性的延迟加载。
hibernate中lazy的使用
lazy,延迟加载
Lazy的有效期:只有在session打开的时候才有效;session关闭后lazy就没效了。
lazy策略可以用在:
* <class>标签上:可以取值true/false
* <property>标签上,可以取值true/false,这个特性需要类增强
* <set>/<list>等集合上,可以取值为true/false/extra
* <one-to-one>/<many-to-one>等标签上,可以取值false/proxy/no-proxy
一、概念:即两者之间存在关联关系,那么在加载主对象的时候,对副对象的加载处理,是延迟或立即,比如说公司(主)-》部门(副).
二、分析
1.立即检索
实现方法:将<set/>属性的lazy设为false,即不延迟加载.注解是@fetch = FetchType.EAGER. 检索方式:加载主对象的同时加载副对象信息,反之亦然.
优点:即使当前session关闭,处于游离状态,也能获取到关联对象.
缺点:执行的SQL太多,增加数据库压力,还可能加载一些不需要的对象,即浪费时间,又浪费缓存控件.
优先使用场合:
a.在业务或程序中,需要立即访问关联对象时可以使用.
b.使用二级缓存.
2.延迟检索
实现方法:将<set/>属性的lazy设为true,即延迟加载.注解是@fetch = FetchType.LAZY.
检索方式:不立即检索与之关联的对象,但是会为关联对象创建一个代理对象,这个代理对象只初始化一个OID,只有这个代理对象的属性被访问时,才初始化该代理对象.
优点,缺点:与立即检索相反.
优先使用场合:
a.一对多或多对多的关联使用.
b.在程序中不需要立即访问或者该关联的对象不需要访问的时候.
什么时候用延迟加载
例如:银行开户,一个人可以开多个帐户,一个帐户只能属于一个人,所以在用户类里包含一个帐户的集合,帐户类里包含一个用户类型,他们之间是一对多的关系.
如过你在查询的时候,通过用户查询是,如果只想查到用户就用(hibernate)默认的延迟加载,这样效率也高,如果你想把该用户的的所有帐户都一同查出来,那就需要立即加载了,这样一来如果一个用户对应的帐户比较多的话,他的效率是很低的.
设置加载方式一般有两种,一种是通过映射文件(lazy=false),另一种是通过程序的方式来实现的也很简单.
第三部分 Spring
一、Spirng中的Bean的作用范围有哪些?
singleton、prototype、request、session、global session。
二、ApplicationConext和BeanFactory有什么主要区别?
ApplicationConext在加载ApplicationContext实例时,会自动实例化容器的全部Bean;而BeanFactory等到程序需要Bean实例时才创建Bean.。
三、Spring中的Bean和传统JavaBean有什么不同?
用处不同:传统JavaBean更多作为值对象传递参数,Spring的Bean用处几乎无所不包,任何应用组件都被称为Bean。
写法不同:传统JavaBean作为值对象,要求每个属性都提供getter和setter方法;但Spring的Bean只需为接受设值注入的属性提供setter方法。
四、spring工作机制及为什么要用?
1.spring mvc将所有的请求都提交给DispatcherServlet,它会委托应用系统的其他模块负责负责对请求进行真正的处理工作。
2.DispatcherServlet查询一个或多个HandlerMapping,找到处理请求的Controller.
3.DispatcherServlet将请求提交到目标Controller
4.Controller进行业务逻辑处理后,会返回一个ModelAndView
5.Dispathcher查询一个或多个ViewResolver视图解析器,找到ModelAndView对象指定的视图对象
6.视图对象负责渲染返回给客户端。
五、IOC:控制反转也叫依赖注入:
利用了工厂模式,将对象交给容器管理,你只需要在spring配置文件总配置相应的bean,以及设置相关的属性,让spring容器来生成类的实例对象以及管理对象。在spring容器启动的时候,spring会把你在配置文件中配置的bean都初始化好,然后在你需要调用的时候,就把它已经初始化好的那些bean分配给你需要调用这些bean的类(假设这个类名是A),分配的方法就是调用A的setter方法来注入,而不需要你在A里面new这些bean了。
六、AOP:面向切面编程:
AOP可以说是对OOP的补充和完善。OOP引入封装、继承和多态性等概念来建立一种对象层次结构,用以模拟公共行为的一个集合。当我们需要为分散的对象引入公共行为的时候,OOP则显得无能为力。也就是说,OOP允许你定义从上到下的关系,但并不适合定义从左到右的关系。例如日志功能。日志代码往往水平地散布在所有对象层次中,而与它所散布到的对象的核心功能毫无关系。在OOP设计中,它导致了大量代码的重复,而不利于各个模块的重用。
将程序中的交叉业务逻辑(比如安全,日志,事务等),封装成一个切面,然后注入到目标对象(具体业务逻辑)中去。
实现AOP的技术,主要分为两大类:一是采用动态代理技术,利用截取消息的方式,对该消息进行装饰,以取代原有对象行为的执行;二是采用静态织入的方式,引入特定的语法创建“方面”,从而使得编译器可以在编译期间织入有关“方面”的代码
第四部分 Struts2
一、struts2执行过程:
1 、客户端向Servlet容器(如Tomcat)提交一个请求,请求经过一系列过滤器(如ActionContextCleanUp
过滤器等)
2 、核心控制器被调用,询问ActionMapper来决定请求是否需要调用某个Action
3 、如果ActionMapper决定需要调用某个Action,核心控制器把控制权委派给ActionProxy (备注:
JSP请求无需调用Action)
4 、ActionProxy通过Configuration Manager询问框架的配置文件(struts.xml),找到需调用的Action
类
5 、ActionProxy 创建一个ActionInvocation 的实例
6 、 ActionInvocation 负责调用Action ,在此之前会依次调用所有配置的拦截器
7 、Action 执行完毕,ActionInvocation 负责根据结果码字符串在struts.xml 的配置中找到对应的返
回结果
8 、拦截器被再次执行
9 、过滤器被再次执行
二、拦截器
Params拦截器 负责将请求参数设置为Action 属性
servletConfig 拦截器 将源于Servlet API 的各种对象注入到Action
fileUpload 拦截器 对文件上传提供支持
exception 拦截器 捕获异常,并且将异常映射到用户自定义的错误页面
validation 拦截器 调用验证框架进行数据验证
workflow 拦截器 调用Action 类的validate() ,执行编码验证
三、struts1与struts2的区别:
1、struts1要求Action类继承一个抽象基类,而不是接口。 struts2的action类可以实现一个action接口,也可以实现其他接口。
2、sturts1 action是单例模式,线程是不安全的。 struts2 action线程是安全的,action为每一个请求都生成了一个实例。
3、sturts1过去依赖serlet API,不容易测试。 struts2不依赖于容器,允许Action脱离容器单独被测试。
4、Struts1 使用ActionForm对象捕获输入。所有的ActionForm必须继承一个基类。 Struts 2直接使用Action属性作为输入属性,消除了对第二个输入对象的需求。
5、Struts1整合了JSTL,因此使用JSTL EL。这种EL有基本对象图遍历,但是对集合和索引属性的支持很弱。Struts2可以使用JSTL,但是也支持一个更强大和灵活的表达式语言
6、Struts 1使用标准JSP机制把对象绑定到页面中来访问。 Struts 2 使用 "ValueStack"技术,使taglib能够访问值而不需要把你的页面(view)和对象绑定起来。
7、Struts 1 ActionForm 属性通常都是String类型。Struts1使用Commons-Beanutils进行类型转换。 Struts2 使用OGNL进行类型转换。提供基本和常用对象的转换器。
8、Struts 1支持在ActionForm的validate方法中手动校验,或者通过Commons Validator的扩展来校验。 Struts2支持通过validate方法和XWork校验框架来进行校验。
9、Struts1支持每一个模块有单独的Request Processors(生命周期),但是模块中的所有Action必须共享相同的生命周期。 Struts2支持通过拦截器堆栈(Interceptor Stacks)为每一个Action创建不同的生命周期。堆栈能够根据需要和不同的Action一起使用。
四、核心控制器FilterDispatcher是Struts 2框架的基础,包含了框架内部的控制流程和处理机制。 业务控制器Action和业务逻辑组件是需要用户来自己实现的。用户在开发Action和业务逻辑组件的同时,还需要编写相关的配置文件,供核心控制器FilterDispatcher来使用。