Spring加载bean的时候构造函数何时调用、@PostConstruct何时调用、实现了BeanPostProcessor接口的bean中的postProcessAfterInitialization和postProcessBeforeInitialization何时调用?你是否清楚呢?若是清楚的话能够直接忽略该篇文章!!!
最近来了几个新人,被问了一个和bean生命周期相关的一个知识点,解决新人的问题后本身再写了一个demo,目的是为了清晰的描述整个bean的生命周期。git
注意注意,如下demo有五个类,可能会引发部分人不适,建议能够直接跳到最后看 最终总结,或者本身下载源码运行下。
demo地址: https://github.com/wiatingpub...
首先给出一个实现了BeanFactoryPostProcessor的类,目的是为了比较清晰的看出postProcessBeanFactory接口被调用的时间点。github
/** * BeanFactoryPostProcessor是bean工厂的处理器 */ @Component public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor { public MyBeanFactoryPostProcessor() { super(); System.out.println("【BeanFactoryPostProcessor】实现类postProcessBeanFactory的构造函数"); } // 容许咱们在工厂里全部的bean被加载进来后可是还没初始化前,对全部bean的属性进行修改也能够add属性值,该操做在对应bean的构造函数执行前 @Override public void postProcessBeanFactory(ConfigurableListableBeanFactory arg0) throws BeansException { System.out .println("【BeanFactoryPostProcessor.postProcessBeanFactory】,来自MyBeanFactoryPostProcessor"); //获取到Spring中全部的beanName String[] beanStr = arg0.getBeanDefinitionNames(); //循环打印 for (String beanName : beanStr) { System.out.print("bean name:" + beanName + ";"); } System.out.println(); } } 这里给出一个实现了BeanPostProcessor的类,目的是为了看出postProcessAfterInitialization、postProcessBeforeInitialization调用的时间点。 /** * 完成bean实例化、配置以及其余初始化方法先后要添加一些本身逻辑处理则要实现接口BeanPostProcessor */ @Component public class MyBeanPostProcessor implements BeanPostProcessor { public MyBeanPostProcessor() { super(); System.out.println("【MyBeanPostProcessor】BeanPostProcessor实现类的构造函数"); } // 实例化、依赖注入完毕,在调用显示的初始化以前完成一些定制的业务 @Override public Object postProcessAfterInitialization(Object arg0, String arg1) throws BeansException { if (arg0.getClass() == TestBeanA.class || arg0.getClass() == TestBeanB.class) { System.out .println("【BeanPostProcessor.postProcessAfterInitialization】来自MyBeanPostProcessor,beanName:" + arg1); } return arg0; } // 实例化、依赖注入、初始化后完成一些定制的业务 @Override public Object postProcessBeforeInitialization(Object arg0, String arg1) throws BeansException { if (arg0.getClass() == TestBeanA.class || arg0.getClass() == TestBeanB.class) { System.out .println("【BeanPostProcessor.postProcessBeforeInitialization】来自MyBeanPostProcessor,beanName:" + arg1); } return arg0; } }
这里给出继承了InstantiationAwareBeanPostProcessorAdapter的子类,目的是为了看出postProcessBeforeInitialization、postProcessAfterInitialization、postProcessPropertyValues被调用的时间点。面试
/** * 适配器类,基类是BeanPostProcessor的实现类 */ @Component public class MyInstantiationAwareBeanPostProcessor extends InstantiationAwareBeanPostProcessorAdapter { public MyInstantiationAwareBeanPostProcessor() { super(); System.out .println("【MyInstantiationAwareBeanPostProcessor】InstantiationAwareBeanPostProcessorAdapter实现类的构造函数"); } // 接口方法、实例化Bean以前调用 @Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { if (bean.getClass() == TestBeanA.class || bean.getClass() == TestBeanB.class) { System.out .println("【InstantiationAwareBeanPostProcessorAdapter.postProcessBeforeInitialization】来自MyInstantiationAwareBeanPostProcessor,beanName:" + beanName); } return bean; } // 接口方法、实例化Bean以后调用 @Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { if (bean.getClass() == TestBeanA.class || bean.getClass() == TestBeanB.class) { System.out .println("【InstantiationAwareBeanPostProcessorAdapter.postProcessAfterInitialization】来自MyInstantiationAwareBeanPostProcessor,beanName:" + beanName); } return bean; } // 接口方法、设置某个属性时调用 @Override public PropertyValues postProcessPropertyValues(PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException { if (bean.getClass() == TestBeanA.class || bean.getClass() == TestBeanB.class) { System.out .println("【InstantiationAwareBeanPostProcessorAdapter.postProcessPropertyValues】来自MyInstantiationAwareBeanPostProcessor,beanName:" + beanName); } return pvs; }
这个就牛逼了,直接交给applicationContext.xml注入而且实现了BeanFactoryAware, BeanNameAware,InitializingBean,DisposableBean四个接口类,目的是为了清晰的看出如下好几个接口被调用的时间点。spring
public class TestBeanA implements BeanFactoryAware, BeanNameAware, InitializingBean, DisposableBean { private String name; private String address; private int phone; private BeanFactory beanFactory; private String beanName; @PostConstruct public void init() { System.out.println("【TestBeanA.@PostConstruct】"); } public TestBeanA() { System.out.println("【TestBeanA.默认构造器】"); } public TestBeanA(String name) { System.out.println("【TestBeanA.带参构造器】"); } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } public int getPhone() { return phone; } public void setPhone(int phone) { this.phone = phone; } @Override public String toString() { return "TestBeanA [address=" + address + ", name=" + name + ", phone=" + phone + "]"; } // 这是BeanFactoryAware接口方法 @Override public void setBeanFactory(BeanFactory arg0) throws BeansException { System.out .println("【BeanFactoryAware.setBeanFactory】来自TestBeanA"); this.beanFactory = arg0; } // 这是BeanNameAware接口方法 @Override public void setBeanName(String arg0) { System.out.println("【BeanNameAware.setBeanName】来自TestBeanA"); this.beanName = arg0; } // 这是InitializingBean接口方法 @Override public void afterPropertiesSet() throws Exception { System.out .println("【InitializingBean.afterPropertiesSet】来自TestBeanA"); } // 这是DiposibleBean接口方法 @Override public void destroy() throws Exception { System.out.println("【DiposibleBean.destory】来自TestBeanA"); } // 经过<bean>的init-method属性指定的初始化方法 public void myInit() { System.out.println("【TestBeanA.myInit】"); } // 经过<bean>的destroy-method属性指定的初始化方法 public void myDestory() { System.out.println("【TestBeanA.destroy-method】"); } }
TestBeanB的做用比较简单,为了看出内部数据成员有其余容器Bean的时候Spring是如何加载bean的。编程
@Component public class TestBeanB { @Autowired private TestBeanA testBeanA; public TestBeanB() { System.out.println("【TestBeanB.默认构造器】"); } }
这个是启动类。缓存
@SpringBootApplication @ImportResource(locations = {"classpath:applicationContext.xml"}) public class DemoApplication { public static void main(String[] args) { SpringApplication.run(DemoApplication.class, args); } }
虽然使用的是SpringBoot,这里还使用xml是为了看看init-method和destroy-method的调用时间。微信
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="testBeanA" class="com.example.demo.bean.TestBeanA" init-method="myInit" destroy-method="myDestory"> <property name="name" value="关注微信公众号 饭说编程"/> </bean> </beans>
很长很长的代码算是都给出来了,接下来看下运行后给出的结果app
【BeanFactoryPostProcessor】实现类postProcessBeanFactory的构造函数 【BeanFactoryPostProcessor.postProcessBeanFactory】,来自MyBeanFactoryPostProcessor 【MyBeanPostProcessor】BeanPostProcessor实现类的构造函数 【MyInstantiationAwareBeanPostProcessor】InstantiationAwareBeanPostProcessorAdapter实现类的构造函数 【TestBeanB.默认构造器】 【InstantiationAwareBeanPostProcessorAdapter.postProcessPropertyValues】来自MyInstantiationAwareBeanPostProcessor,beanName:testBeanB 【TestBeanA.默认构造器】 【InstantiationAwareBeanPostProcessorAdapter.postProcessPropertyValues】来自MyInstantiationAwareBeanPostProcessor,beanName:testBeanA 【BeanNameAware.setBeanName】来自TestBeanA 【BeanFactoryAware.setBeanFactory】来自TestBeanA 【BeanPostProcessor.postProcessBeforeInitialization】来自MyBeanPostProcessor,beanName:testBeanA 【InstantiationAwareBeanPostProcessorAdapter.postProcessBeforeInitialization】来自MyInstantiationAwareBeanPostProcessor,beanName:testBeanA 【TestBeanA.@PostConstruct】 【InitializingBean.afterPropertiesSet】来自TestBeanA 【TestBeanA.myInit】 【BeanPostProcessor.postProcessAfterInitialization】来自MyBeanPostProcessor,beanName:testBeanA 【InstantiationAwareBeanPostProcessorAdapter.postProcessAfterInitialization】来自MyInstantiationAwareBeanPostProcessor,beanName:testBeanA 【BeanPostProcessor.postProcessBeforeInitialization】来自MyBeanPostProcessor,beanName:testBeanB 【InstantiationAwareBeanPostProcessorAdapter.postProcessBeforeInitialization】来自MyInstantiationAwareBeanPostProcessor,beanName:testBeanB 【BeanPostProcessor.postProcessAfterInitialization】来自MyBeanPostProcessor,beanName:testBeanB 【InstantiationAwareBeanPostProcessorAdapter.postProcessAfterInitialization】来自MyInstantiationAwareBeanPostProcessor,beanName:testBeanB 【DiposibleBean.destory】来自TestBeanA 【TestBeanA.destroy-method】
貌似又是一段看完头晕脑胀的恶心代码,不过不方不方,直接进入分析阶段,跟着分析入手就简单多了。ide
首先从函数
【BeanFactoryPostProcessor】实现类postProcessBeanFactory的构造函数 【BeanFactoryPostProcessor.postProcessBeanFactory】,来自MyBeanFactoryPostProcessor 【MyBeanPostProcessor】BeanPostProcessor实现类的构造函数 【MyInstantiationAwareBeanPostProcessor】InstantiationAwareBeanPostProcessorAdapter实现类的构造函数
能够看出执行顺序是:
BeanFactoryPostProcessor是bean工厂的处理器
postProcessBeanFactory函数容许咱们在工厂里全部的bean被加载进来后可是还没初始化前,对全部bean的属性进行修改也能够add属性值
完成bean实例化、配置以及其余初始化方法先后要添加一些本身逻辑处理则要实现接口BeanPostProcessor
适配器类,基类是BeanPostProcessor的实现类
再从
【TestBeanB.默认构造器】 【InstantiationAwareBeanPostProcessorAdapter.postProcessPropertyValues】来自MyInstantiationAwareBeanPostProcessor,beanName:testBeanB
能够看到,此处spring容器先扫描到了TestBeanB,所以调用顺序是
postProcessPropertyValues在接口方法、设置某个属性时调用,经过实验看到实例化一个Bean的时候也会调用该接口方法
以后实例化TestBeanB的时候发现内部注入了TestBeanA,所以Spring转而实例化TestBeanA。
接下来看到的是TestBeanA的实例化过程当中调用的顺序
【TestBeanA.默认构造器】 【InstantiationAwareBeanPostProcessorAdapter.postProcessPropertyValues】来自MyInstantiationAwareBeanPostProcessor,beanName:testBeanA 【BeanNameAware.setBeanName】来自TestBeanA 【BeanFactoryAware.setBeanFactory】来自TestBeanA 【BeanPostProcessor.postProcessBeforeInitialization】来自MyBeanPostProcessor,beanName:testBeanA 【InstantiationAwareBeanPostProcessorAdapter.postProcessBeforeInitialization】来自MyInstantiationAwareBeanPostProcessor,beanName:testBeanA 【TestBeanA.@PostConstruct】 【InitializingBean.afterPropertiesSet】来自TestBeanA 【TestBeanA.myInit】 【BeanPostProcessor.postProcessAfterInitialization】来自MyBeanPostProcessor,beanName:testBeanA 【InstantiationAwareBeanPostProcessorAdapter.postProcessAfterInitialization】来自MyInstantiationAwareBeanPostProcessor,beanName:testBeanA
能够从源码看到TestBeanA实现了接口BeanNameAware
能够从源码看到TestBeanA实现了接口BeanFactoryAware
能够从源码看到TestBeanA实现了接口InitializingBean
能够看到该init-method接口是在applicationContext中init-method配置上的
等TestBeanA实例化结束后,则继续TestBeanB的实例化路程
【BeanPostProcessor.postProcessBeforeInitialization】来自MyBeanPostProcessor,beanName:testBeanB 【InstantiationAwareBeanPostProcessorAdapter.postProcessBeforeInitialization】来自MyInstantiationAwareBeanPostProcessor,beanName:testBeanB 【BeanPostProcessor.postProcessAfterInitialization】来自MyBeanPostProcessor,beanName:testBeanB 【InstantiationAwareBeanPostProcessorAdapter.postProcessAfterInitialization】来自MyInstantiationAwareBeanPostProcessor,beanName:testBeanB
最后
【DiposibleBean.destory】来自TestBeanA 【TestBeanA.destroy-method】
TestBeanA实现了DiposibleBean接口,实现了destroy接口
能够看到该myDestory接口是在applicationContext中destroy-method配置上的。
【超重点,面试回答模板,老牛逼了】
以后真正进入一个bean的生命周期过程
走到这一步之后就能够应用这个Bean了,而这个Bean是一个Singleton的,虽然在Spring配置文件中也能够配置非Singleton,这里不作赘述。
走入销毁阶段
Java源码分析、go语言应用、微服务,更多干货欢迎关注公众号: