Spring中bean的生命周期和方法注入和事务
1.Bean生命周期
可以在依赖注入过程之后或销毁之前执行特性行为(反射)
依赖注入过程:
1:Bean的建立:容器寻找Bean的定义信息并将其实例化。
2:属性注入:使用依赖注入,Spring按照Bean定义信息配置Bean所有属性
3:BeanNameAware的setBeanName():如果Bean类有实现org.springframework.beans.BeanNameAware接口,工厂调用Bean的setBeanName()方法传递Bean的ID。
4:BeanFactoryAware的setBeanFactory():如果Bean类有实现org.springframework.beans.factory.BeanFactoryAware接口,工厂调用setBeanFactory()方法传入工厂自身。
5:BeanPostProcessors的ProcessBeforeInitialization()如果有org.springframework.beans.factory.config.BeanPostProcessors和Bean关联,那么其postProcessBeforeInitialization()方法将被将被调用。
6:initializingBean的afterPropertiesSet():如果Bean类已实现org.springframework.beans.factory.InitializingBean接口,则执行他的afterProPertiesSet()方法
7:Bean定义文件中定义init-method:可以在Bean定义文件中使用"init-method"属性设定方法名称。
8:BeanPostProcessors的ProcessaAfterInitialization(),如果有任何的BeanPostProcessors实例与Bean实例关联,则执行BeanPostProcessors实例的ProcessaAfterInitialization()方法
销毁过程:
1:DisposableBean的destroy(),在容器(ApplictionContext)关闭时,如果Bean类实现org.springframework.beans.factory.DisposableBean接口,则执行他的destroy()方法
2:Bean定义文件中定义destroy-method,在容器关闭时,可以在Bean定义文件中使用"destroy-method"属性设定方法名称。
2.方法注入
在大部分情况下,容器中的bean都是singleton类型的。如果一个singleton bean要引用另外一个singleton bean,或者一个非singleton bean要引用另外一个非singleton bean时,通常情况下将一个bean定义为另一个bean的property值就可以了。
不过对于具有不同生命周期的bean来说这样做就会有问题了,比如在调用一个singleton类型bean A的某个方法时,需要引用另一个非singleton(prototype)类型的bean B,对于bean A来说,容器只会创建一次,这样就没法在需要的时候每次让容器为bean A提供一个新的的bean B实例
对于上面的问题Spring提供了三种解决方案:
- 放弃控制反转。通过实现ApplicationContextAware接口让bean A能够感知bean 容器,并且在需要的时候通过使用getBean("B")方式向容器请求一个新的bean B实例。
- Lookup方法注入。Lookup方法注入利用了容器的覆盖受容器管理的bean方法的能力,从而返回指定名字的bean实例。
- 自定义方法的替代方案。该注入能使用bean的另一个方法实现去替换自定义的方法。
第一种方法,实现接口,造成了和Spring API耦合,严重污染了代码。第三种不常用。
通常,采用方法注入。
使用这种方式很简单,因为Spring已经为我们做了很大一部分工作,我们要做的就是bean配置和业务类。
- 首先修改CommandManager类为abstract的,修改createCommand方法也为abstract的。
- 去掉ApplicationContextAware的实现及相关set方法和applicationContext变量定义
- 修改bean配置文件,在commandManager Bean中增加<lookup-method name="createCommand" bean="asyncCommand"/>。
- 其他保持不变
这样,每次调用createCommand方法时都是生成一个新的实例,避免一直使用最早注入的Bean实例。
实际上,Spring使用了CGLIB的库,使用动态代理来生成一个目标单例类的子类,重写lookup的方法(其中生成新的类)。
3.Spring事务