1.Spring的两大特性
AOP(Aspect Oriented Programming,面向切面编程)与IOC(Inverse of Control,控制反转)。
追问:Spring的AOP原理是什么?实现AOP的方式?
Spring AOP的底层使用的是动态代理,有两种实现方式:
JDK动态代理:利用反射机制生成一个实现代理接口的匿名类,在调用具体方法前调用InvokeHandler来处理。
CGlib动态代理:以CGLIB(Code Generation Library)的方式进行代理,它采用底层字节码技术,将代理对象类的class文件加载进来,通过修改其字节码生成子类来处理。
区别:JDK 代理只能对实现接口的类生成代理;CGLIB 是针对类实现代理,继承指定类并生成一个子类,因此不能代理 final 修饰的类。
在Spring中优先使用哪种AOP?
(1)如果目标对象实现了接口,默认采用JDK的动态代理,但也可强制使用CGlib动态代理;
(2)如果目标对象没有实现接口,那么必须采用CGlib库;
Spring会自动在JDK动态代理和CGlib之间转换。
Spring的bean的初始化及生命周期
(1)实例化 Bean:
对于BeanFactrory容器,当向容器请求一个尚未初始化的bean时,或初始化bean的时候需要注入另一个尚未初始化的bean的依赖时,容器就会调用createbean进行实例化;
对于ApplicationContext容器,当容器启动结束后,通过获取BeanDefinition对象中的信息,实例化所有的bean。
(2)设置对象属性(依赖注入):
实例化对象后的bean呗封装在BeanWrapper对象中,然后Spring根据BeanDefinition中的信息以及通过BeanWrapper提供的设置属性的接口完成依赖注入。
(3)处理Aware接口:
Spring会检测该Bean是否实现了xxxAware接口,并将相关的xxxAware实例注入给Bean:
①如果该 Bean 实现了 BeanNameAware 接口,会调用它实现的 setBeanName (String beanId) 方法,入参是 Spring 配置文件中 Bean 的 id 值;
②如果该Bean实现了BeanFactoryAware接口,会调用它实现的setBeanFactory()方法
,传递的是Spring的本身。
③如果该Bean已经实现ApplicationContextAware 接口,会调用 setApplicationContext (ApplicationContext) 方法,入参是 Spring 上下文;
(4)处理 BeanPostProcessor 接口:
如果该 Bean 实现了实现了 BeanPostProcessor 接口,那将会调用 postProcessBeforeInitialization (Object obj, String s) 方法;
(5)InitializingBean 与 init-method:
如果该 Bean 在 xml 中配置了 init-method 属性,则会自动调用其配置的初始化方法。
以上几个步骤完成后,Bean 就已经被正确创建了,之后就可以使用这个 Bean 了。
(6)处理 DisposableBean 接口:
当 Bean 不再需要时,会经过清理阶段,如果 Bean 实现了 DisposableBean 这个接口,会调用其实现的 destroy () 方法;
(7)处理 destroy-method 属性:
最后,如果这个 Bean 的 Spring 配置中配置了 destroy-method 属性,会自动调用其配置的销毁方法。
问题 3:Spring 支持的事务管理类型有哪些?各自的优缺点是什么
参考答案:
(1)编程式事务管理:是指在代码中手动的管理事务的提交、回滚等操作;
(2)声明式事务管理:将事务管理作为一个 “切面” 代码单独编写,只用关心核心业务逻辑代码,然后通过 AOP 技术将事务管理的 “切面” 代码织入到业务类中。
声明式事务的缺点在于只能作用到方法级别,无法做到像编程式事务那样能控制到代码块级别;其优点则在于可以将业务代码和事务管理分离,编程式事务则对业务代码侵入式太强。
Spring 事务的本质其实就是数据库对事务的支持,没有数据库的事务支持,spring 是无法提供事务功能的。对于纯 JDBC 操作数据库,想要用到事务,可以按照以下步骤进行:
(1)获取连接 Connection con = DriverManager.getConnection ();
(2)开启事务 con.setAutoCommit (true/false);
(3)执行增删查改;
(4)提交事务 / 回滚事务 con.commit () /con.rollback ();
(5)关闭连接 conn.close ();
使用 Spring 的事务管理功能后,我们可以不再写步骤 2 和 4 的代码,而是由 Spirng 自动完成。
在编程式事务中,即通过编写代码实现事物管理,包括定义事务的开始,程序正常执行后的事物提交,异常时进行的事务回滚;
在声明式事务中,通过 AOP 功能来实现声明式事务处理的,具体操作(比如事务实行的配置和读取,事务对象的抽象),用 TransactionProxyFactoryBean 接口来使用 AOP 功能,生成 proxy 代理对象,通过 TransactionInterceptor 完成对代理方法的拦截,将事务处理的功能编织到拦截的方法中。说得更详细一点:
(1)Spring 事务处理模块是通过 AOP 功能为没有编写事务代码但加上了 @Transactional 注解的类生成代理。
(2)生成代理的过程中会读取 @Transactional 注解中的配置,比如传播行为、隔离级别、事务超时等。
(3)生成的代理会拦截目标对象的外部方法调用,自动开启事务、自动提交事务或回滚。
三、总结
Spring 是 Java 应用最广泛的框架,也是 Java 企业级开发事实上的标准,通常是框架面试题的第一选择。 这类面试题可深可浅,文章最开始提到的三类框架面试题:使用性面试题、原理性面试题、开放性面试题,从难度上讲是层层递进的关系。在一次面试中,一般不会这三类题都考,面试官有时候会一直问直到候选人答不出来以确定候选人的真实水平,有时候则适可而止达到岗位要求即可,这是不同公司不同岗位决定的。不过对面试题来说,这三类题都要有所准备,在平常使用过程中,也要多问问为什么,多想想 WHAT、HOW、WHY。
框架题也是强实践性的题,如果确实没有接触过,那么面试时遇到相关题目时直接告知面试官即可,不必强撑着回答,因为这种情景下的回答必然是千疮百孔,反而适得其反,好的面试官则会适时调整面试方向。