Spring InitializingBean接口
前言
在 Spring Bean 初始化的过程中,有几种初始化参数的方式
- Constructor 构造方法
- @PostConstruct 注解方式
- **InitializingBean **接口方式
- init-method 初始化方法(init-method=”testInit”)
执行顺序就是上面的顺序,其它说明
spring
为bean
提供了两种初始化bean
的方式,实现InitializingBean
接口,实现afterPropertiesSet
方法,或者在配置文件中同过init-method
指定,两种方式可以同时使用- 实现
InitializingBean
接口是直接调用afterPropertiesSet
方法,比通过反射调用init-method
指定的方法效率相对来说要高点。但是init-method
方式消除了对spring
的依赖 - 如果调用
afterPropertiesSet
方法时出错,则不调用init-method
指定的方法。 @PostConstruct
注解后的方法在BeanPostProcessor
前置处理器中就被执行了,所以当然要先于InitializingBean
和init-method
执行了。
InitializingBean
实现
有时候会遇到这样的问题:
在我们将一个Bean交给Spring
管理的时候,有时候我们的Bean
中有某个属性需要注入,但是又不能通过一般的方式注入,什么意思呢?举个栗子:首先我们有个Service
,在该Service
中有一个属性,但是该属性不支持Spring
注入,只能通过Build
或者new
的方式创建(比如StringBuffer之类的),但是我们想在Spring
配置Bean的时候一起将该属性注入进来,这时候该怎么办呢?这时候可以通过实现InitializingBean
接口来解决!
1 |
|
上面的列子实现了InitializingBean
接口并实现其afterPropertiesSet
方法,通过这种方式就可以实现一些比较特殊的注入,当然也可以在afterPropertiesSet
方法中添加一些其他逻辑来控制创建的对象。当然除了InitializingBean
接口,还有一个类似的接口:DisposableBean
,该接口的作用是在对象销毁时调用。
原理:
首先说说spring的IOC容器初始化过程,首先Spring会定位BeanDefinition
资源文件,然后会一个一个的去加载所有BeanDefinition
,这里的BeanDefinition
就是指的Bean的资源文件,即:在XML中配置的Bean和通过注解装配的Bean,在加载完所有BeanDefinition
之后,会将这些BeanDefinition
注册到一个HashMap中。到此spring的IOC初始化完成,那么依赖注入发生在哪里呢?在用户第一次向IOC容器索要Bean时才开始依赖注入过程(也可以通过配置lazy-init属性让容器初始化的时候就对Bean预实例化)那究竟afterPropertiesSet()
方法的调用是在哪个时间点呢?通过查看该方法上的注释:
1 | Invoked by a BeanFactory after it has set all bean properties supplied (and satisfied BeanFactoryAware and ApplicationContextAware). |
可以看到在Bean所有的属性都被注入之后会去调用这个afterPropertiesSet()
方法,其实在依赖注入完成的时候,spring会去检查这个类是否实现了InitializingBean
接口,如果实现了InitializingBean
接口,就会去调用这个类的afterPropertiesSet()
方法。所以afterPropertiesSet()
方法的执行时间点就很清楚了,发生在所有的properties
被注入后。