SpringSpring中BeanPostProcessor
Posted 九师兄
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SpringSpring中BeanPostProcessor相关的知识,希望对你有一定的参考价值。
1.概述
对文章:SpringBoot : 定制化Bean的利器:BeanPostProcessor & BeanFactoryPostProcessor 的一个补充。
测试所使用的Spring版本:4.3.12.RELEASE
一、bean的生命周期:创建—>初始化—>销毁
容器管理 bean 的生命周期,我们可以自定义初始化和销毁方法,容器在 bean 进行到当前生命周期的时候来调用我们自定义的初始化和销毁方法。
1、bean的创建:
单实例:在容器启动时创建对象;
多实例:在每次获取时创建对象。
2、bean的初始化:
单实例:对象创建完成,并赋值好,调用初始化方法
多实例:获取对象时,创建对象,赋值,然后调用初始化方法
3、bean的销毁:
单实例:容器关闭时销毁
多实例:容器不会管理这个bean,容器不会调用销毁方法。
二、插手初始化/销毁过程的四种操作方式:
1、指定初始化和销毁方法:通过 @Bean 注解指定 init-method 和 destroy-method
第一步:实体类
@Component
public class Car {
public Car() {
System.out.println("car constructor...");
}
public void init() {
System.out.println("car ... init...");
}
public void detory() {
System.out.println("car ... detory...");
}
}
第二步:配置
@Configuration
public class MainConfigOfLifeCycle {
//@Scope("prototype") //多实例
@Bean(initMethod="init",destroyMethod="detory")
public Car car(){
return new Car();
}
}
第三步:测试
public class IOCTest_LifeCycle {
@Test
public void test01(){
//创建 IOC 容器
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfigOfLifeCycle.class);
System.out.println("容器创建完成...");
//applicationContext.getBean("car"); //多实例测试用
//关闭容器
applicationContext.close();
}
}
第四步:结果
六月 03, 2019 2:28:08 下午 org.springframework.context.annotation.AnnotationConfigApplicationContext prepareRefresh
信息: Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@2db0f6b2: startup date [Mon Jun 03 14:28:08 CST 2019]; root of context hierarchy
六月 03, 2019 2:28:09 下午 org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor <init>
car constructor...
car ... init...
容器创建完成...
六月 03, 2019 2:28:09 下午 org.springframework.context.annotation.AnnotationConfigApplicationContext doClose
信息: Closing org.springframework.context.annotation.AnnotationConfigApplicationContext@2db0f6b2: startup date [Mon Jun 03 14:28:08 CST 2019]; root of context hierarchy
car ... detory...
由上可看出,对于单实例的 bean,容器创建时执行了构造方法和初始化方法,容器创建完成后可直接使用;容器关闭时执行销毁方法。而对于多实例来说,容器创建时不会执行bean的构造方法和初始化方法,只有在使用到bean的时候,才会去执行构造方法和初始化方法,容器关闭时,也不会执行销毁方法。(这里就不贴结果了,有兴趣自己测试就行)
2、通过让 Bean 实现 InitializingBean (定义初始化逻辑),DisposableBean(定义销毁逻辑)
第一步:实体类
@Component
public class Cat implements InitializingBean,DisposableBean {
public Cat(){
System.out.println("cat constructor...");
}
public void destroy() throws Exception {
System.out.println("cat...destroy...");
}
public void afterPropertiesSet() throws Exception {
System.out.println("cat...afterPropertiesSet...");
}
}
第二步:配置
@Configuration
public class MainConfigOfLifeCycle {
@Bean
public Cat cat(){
return new Cat();
}
}
第三步:测试
public class IOCTest_LifeCycle {
@Test
public void test01(){
//创建 IOC 容器
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfigOfLifeCycle.class);
System.out.println("容器创建完成...");
//applicationContext.getBean("cat"); //多实例测试用
//关闭容器
applicationContext.close();
}
}
结果跟之前的是一样的,不再多说了。
3、使用 JSR250:@PostConstruct、@PreDestroy
- @PostConstruct:在 bean 创建完成并且属性赋值完成后执行初始化方法;
- @PreDestroy:在容器销毁 bean 之前通知我们进行清理工作。
实体类如下,其他的操作和上面相同。
@Component
public class Dog {
public Dog(){
System.out.println("dog constructor...");
}
@PostConstruct
public void init(){
System.out.println("Dog....@PostConstruct...");
}
@PreDestroy
public void detory(){
System.out.println("Dog....@PreDestroy...");
}
}
4、BeanPostProcessor【interface】:bean 的后置处理器
在 bean 初始化前后进行一些处理工作:
- postProcessBeforeInitialization:在初始化之前工作
- postProcessAfterIntialization:在初始化之后工作
@Component
public class MyBeanPostProcessor implements BeanPostProcessor {
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("postProcessBeforeInitialization..."+beanName+"=>"+bean);
return bean;
}
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("postProcessAfterInitialization..."+beanName+"=>"+bean);
return bean;
}
}
@Configuration
public class MainConfigOfLifeCycle {
//@Scope("prototype") //多实例
@Bean
public Dog dog(){
return new Dog();
}
@Bean
public MyBeanPostProcessor myBeanPostProcessor(){
return new MyBeanPostProcessor();
}
}
结果:
//省略
dog constructor... //构造方法
postProcessBeforeInitialization...dog=>com.wyq.bean.Dog@1e67a849 //初始化之前
Dog....@PostConstruct... //初始化
postProcessAfterInitialization...dog=>com.wyq.bean.Dog@1e67a849 //初始化之后
容器创建完成...
六月 03, 2019 3:32:25 下午 org.springframework.context.annotation.AnnotationConfigApplicationContext doClose
信息: Closing org.springframework.context.annotation.AnnotationConfigApplicationContext@2db0f6b2: startup date [Mon Jun 03 15:32:24 CST 2019]; root of context hierarchy
Dog....@PreDestroy...
三、BeanPostProcessor原理
1、作用:在 bean 初始化前后进行其他操作。
BeanPostProcessor.postProcessBeforeInitialization
初始化...
BeanPostProcessor.postProcessAfterInitialization
2、初始化之前/之后具体是什么时间?
断点调试,慢慢看:
(1)首先是创建 IOC 容器:new AnnotationConfigApplicationContext(MainConfigOfLifeCycle.class)
(2)紧接着是执行构造方法:
public AnnotationConfigApplicationContext(Class<?>... annotatedClasses) {
this();
this.register(annotatedClasses);
this.refresh();
}
这里调用了 refresh() 方法,刷新容器。
(3)看一下 refresh() 方法
public void refresh() throws BeansException, IllegalStateException {
synchronized(this.startupShutdownMonitor) {
this.prepareRefresh();
ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();
this.prepareBeanFactory(beanFactory);
try {
this.postProcessBeanFactory(beanFactory);
this.invokeBeanFactoryPostProcessors(beanFactory);
this.registerBeanPostProcessors(beanFactory);
this.initMessageSource();
this.initApplicationEventMulticaster();
this.onRefresh();
this.registerListeners();
this.finishBeanFactoryInitialization(beanFactory);//注意
this.finishRefresh();
} catch (BeansException var9) {
if (this.logger.isWarnEnabled()) {
this.logger.warn("Exception encountered during context initialization - cancelling refresh attempt: " + var9);
}
this.destroyBeans();
this.cancelRefresh(var9);
throw var9;
} finally {
this.resetCommonCaches();
}
}
}
(4)refresh 中 调用了 finishBeanFactoryInitialization(beanFactory)
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
//省略
beanFactory.preInstantiateSingletons();
}
(5)finishBeanFactoryInitialization 中调用 preInstantiateSingletons
public void preInstantiateSingletons() throws BeansException {
//......
if (this.isFactoryBean(beanName)) {
//省略...
} else {
this.getBean(beanName);
}
}
}
}
(6)preInstantiateSingletons 调用 getBean,getBean 又调用 getSingleton
public Object getBean(String name) throws BeansException {
return this.doGetBean(name, (Class)null, (Object[])null, false);
}
protected <T> T doGetBean(String name, Class<T> requiredType, final Object[] args, boolean typeCheckOnly) throws BeansException {
//......
if (sharedInstance != null && args == null) {
//......
} else {
//......
try {
//......
if (mbd.isSingleton()) {
sharedInstance = this.getSingleton(beanName, new ObjectFactory<Object>() {
public Object getObject() throws BeansException {
try {
return AbstractBeanFactory.this.createBean(beanName, mbd, args);
} catch (BeansException var2) {
AbstractBeanFactory.this.destroySingleton(beanName);
throw var2;
}
}
});
bean = this.getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
} else if (mbd.isPrototype()) {
//......
} else {
//......
}
} catch (BeansException var23) {
//......
}
}
//......
}
(7)getSingleton 中调用 getObject,由于是第一次,容器中并没有 bean,所以调用 createBean 创建 bean
protected Object createBean(String beanName, RootBeanDefinition mbd, Object[] args) throws BeanCreationException {
//......
Object beanInstance;
//......
beanInstance = this.doCreateBean(beanName, mbdToUse, args);
if (this.logger.isDebugEnabled()) {
this.logger.debug("Finished creating instance of bean '" + beanName + "'");
}
return beanInstance;
}
(8)如何创建 bean,看一下 doCreateBean 方法,调用 initializeBean 初始化了 bean
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, Object[] args) throws BeanCreationException {
//......
Object exposedObject = bean;
try {
//这个也要注意,后面要说
this.populateBean(beanName, mbd, instanceWrapper);
if (exposedObject != null) {
//初始化bean
exposedObject = this.initializeBean(beanName, exposedObject, mbd);
}
} catch (Throwable var18) {
//......
}
//......
try {
this.registerDisposableBeanIfNecessary(beanName, bean, mbd);
return exposedObject;
} catch (BeanDefinitionValidationException var16) {
//......
}
}
(9)initializeBean 中调用了后置处理器 BeanPostProcessor
protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) {
//......
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
//这里调用后置处理器
wrappedBean = this.applyBeanPostProcessorsBeforeInitialization(bean, beanName);
}
try {
//执行初始化方法
this.invokeInitMethods(beanName, wrappedBean, mbd);
} catch (Throwable var6) {
throw new BeanCreationException(mbd != null ? mbd.getResourceDescription() : null, beanName, "Invocation of init method failed", var6);
}
if (mbd == null || !mbd.isSynthetic()) {
//调用后置处理器
wrappedBean = this.applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
//......
return wrappedBean;
}
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName) throws BeansException {
Object result = existingBean;
Iterator var4 = this.getBeanPostProcessors().iterator();
/*
遍历得到容器中所有的BeanPostProcessor,挨个执行beforeInitailization
一旦返回null,跳出for循环,不会执行后面的BeanPostProcessor
*/
do {
if (!var4.hasNext()) {
return result;
}
BeanPostProcessor beanProcessor = (BeanPostProcessor)var4.next();
result = beanProcessor.postProcessBeforeInitialization(result, beanName);
} 以上是关于SpringSpring中BeanPostProcessor的主要内容,如果未能解决你的问题,请参考以下文章