6. bean 的实例化控制 (生命周期回调)
-
bean 的初始化后回调
- 如果想让 bean 在构建完毕后执行一些自定义的操作, 可以让 bean class 实现接口
InitializingBean
的afterPropertiesSet()
方法. - 不建议使用实现
InitializingBean
接口的方法执行回调, 建议在回调函数上使用@PostConstruct
注解, 或在 xml 中配置init-method
属性
<bean id="exampleInitBean" class="examples.ExampleBean" init-method="init"/>
- 如果想让 bean 在构建完毕后执行一些自定义的操作, 可以让 bean class 实现接口
-
bean 的销毁前回调
- 如果想让 bean 在销毁前执行一些自定义的操作, 可以让 bean class 实现接口
DisposableBean
的destroy
方法 - 不建议使用实现
DisposableBean
,接口的方法执行回调, 建议在回调函数上使用@PreDestroy
注解, 或在 xml 中配置destroy-method
属性
<bean id="exampleInitBean" class="examples.ExampleBean" destroy-method="cleanup"/>
- 如果想让 bean 在销毁前执行一些自定义的操作, 可以让 bean class 实现接口
-
配置全局默认的创建销毁回调函数
可以再 xml 的beans
标签中增加default-init-method
和default-destroy-method
标签, 指定全局回调函数. 这样可以不必在每个 bean 上配置init-method
和destroy-method
<beans default-init-method="init"> <bean id="blogService" class="com.something.DefaultBlogService"> <property name="blogDao" ref="blogDao" /> </bean> </beans>
-
总结, 自定义 bean 的初始化和销毁回调函数有3种方法
- 实现
InitializingBean
和DisposableBean
接口 - 自定义
init()`` and
destroy()`` 函数 - 使用
@PostConstruct` 和
@PreDestroy` 注解
- 实现
-
优雅关闭 ApplicationContext
web 版的 ApplicationContext 已经实现优雅关闭, 非 web 版的 ApplicationContext 可以自定义 hook 实现ConfigurableApplicationContext context = new ClassPathXmlApplicationContext("application1.xml"); context.registerShutdownHook(); // AbstractApplicationContext 中实现
-
其它声明周期的回调
- spring 还提供了很多名字带
Aware
后缀的接口, bean class 实现这些接口后, 会在不同生命周期上回调自定义的函数. - 需要注意的是, 这种写法已经破坏了 xml , 或 annotation 配置的 IOC 初衷, 因此, 继承接口定义 bean 的做法只适用于少数基础架构方面的类
- spring 还提供了很多名字带
- BeanPostProcessor
spring 除了提供了单个 bean 级别的生命周期接口, 还提供了整个容器级别的生命周期接口BeanPostProcessor
, 用来对容器内所有 bean 的初始化做回调-
BeanPostProcessor
的方法
BeanPostProcessor
只有2个方法- 初始化前回调:
postProcessBeforeInitialization(Object bean, String beanName)
- 初始化后回调:
postProcessAfterInitialization(Object bean, String beanName)
- 初始化前回调:
-
BeanPostProcessor
与InitializingBean
, 各种aware
接口的调用顺序
这些顺序要看 beanfactory 类里面是怎么调用的, 以AbstractAutowireCapableBeanFactory
为例protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) { if (System.getSecurityManager() != null) { AccessController.doPrivileged((PrivilegedAction<Object>) () -> { invokeAwareMethods(beanName, bean); return null; }, getAccessControlContext()); } else { //若果Bean实现了BeanNameAware、BeanClassLoaderAware、BeanFactoryAware则初始化Bean的属性值 invokeAwareMethods(beanName, bean); } Object wrappedBean = bean; if (mbd == null || !mbd.isSynthetic()) { //applyBeanPostProcessorsBeforeInitialization 方法内部主要是 //用来调用后置处理器BeanPostProcessor的postProcessBeforeInitialization方法 wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName); } try { //Bean如果继承了InitializingBean类则会调用afterPropertiesSet方法,如果设置了init-method方法, //则调用init-method方法,afterPropertiesSet方法在init-method方法之前调用 invokeInitMethods(beanName, wrappedBean, mbd); } catch (Throwable ex) { throw new BeanCreationException( (mbd != null ? mbd.getResourceDescription() : null), beanName, "Invocation of init method failed", ex); } if (mbd == null || !mbd.isSynthetic()) { //applyBeanPostProcessorsAfterInitialization 方法内部主要是, //用来调用后置处理器BeanPostProcessor的postProcessAfterInitialization方法 wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName); } return wrappedBean; }
因此顺序是:
aware
接口 ->BeanPostProcessor.postProcessBeforeInitialization()
-> InitializingBean.afterPropertiesSet ->BeanPostProcessor.postProcessAfterInitialization()
-
BeanPostProcessor
与 AOP 的关系
aop 因为要返回 bean 的代理对象, 而 BeanPostProcessor 的 postProcessAfterInitialization 方法恰恰是在实例化后调用, 所以可以再这个方法内, 返回一个 bean 的代理对象, 从而实现 AOP -
AutowiredAnnotationBeanPostProcessor 的实现
AutowiredAnnotationBeanPostProcessor 是 spring 内部的一个BeanPostProcessor
, 用来自动装配 bean 上的注解字段, setter 方法调用, 和任何其他的装配方法
-
网友评论