浅谈Spring中几个PostProcessor的区别与联系
目录
- Spring几个PostProcessor的区别
- 首先明确 Bean 的生命周期:
- 查看 IOC 容器创建时的调用流程
- spring-postProcessor的执行时机
- BeanPostProcessor:
- postProcessAfterInitialization调用时机:
- InstantiationAwareBeanPostProcessor
- 总结: 执行顺序
Spring几个PostProcessor的区别
首先明确 Bean 的生命周期:
- 首先注册 Bean 的定义信息;
- 然后创建 Bean 的实例;
- 最后初始化 Bean ,放入容器中。
BeanDefinitionRegistryPostProcessor 是在注册 Bean 定义信息前后调用;其中 BeanDefinitionRegistryPostProcessor 是 BeanFactoryPostProcessor 的子类,所以可以使用前者代替后者实现功能。
BeanFactoryPostProcessor 是在创建 Bean 前后调用;
BeanPostProcessor 是在初始化 Bean 前后调用;
查看 IOC 容器创建时的调用流程
refresh 方法的代码如下:
// Allows post-processing of the bean factory in context subclasses.postProcessBeanFactory(beanFactory); // Invoke factory processors registered as beans in the context.invokeBeanFactoryPostProcessors(beanFactory); // Register bean processors that intercept bean creation.registerBeanPostProcessors(beanFactory); // Initialize message source for this context.initMessageSource(); // Initialize event multicaster for this context.initApplicationEventMulticaster(); // Initialize other special beans in specific context subclasses.onRefresh(); // Check for listener beans and register them.registerListeners(); // Instantiate all remaining (non-lazy-init) singletons.finishBeanFactoryInitialization(beanFactory); // Last step: publish corresponding event.finishRefresh();
其中的 invokeBeanFactoryPostProcessors 就执行了注册定义信息和创建 Bean 的方法;而 finishBeanFactoryInitialization 执行了初始化 Bean 的方法。
具体的执行顺序大家可以自行打断点调试,由于涉及的源码过多,这里不再展示。
spring-postProcessor的执行时机 spring bean 的生命周期粗糙的分为以下步骤。
实例化(创建一个属性都为空的对象)---------》属性填充(populateBean,下文中这个步骤我都称为初始化)-----------》init方法的执行(invokerInitMethods,下文称为init)postprocessor的方法就是穿插在这三个大的步骤中。
BeanPostProcessor:
文章图片
postProcessBeforeInitialization调用时机
文章图片
?
向上找调用者:
文章图片
继续向上:
文章图片
看以看出populateBean(初始化bean)-------------------》beanpostBeforeInitialization---------------------------------->invokeinitMethods(配置的init-method)
postProcessAfterInitialization调用时机:
文章图片
向上:
文章图片
可以看出在init-method方法之后
看以看出populateBean(初始化bean)-------------------》beanpostBeforeInitialization---------------------------------->invokeinitMethods(配置的init-method)------->postProcessAfterInitialization
public class MBeanPostProcessor implements BeanPostProcessor { @Override//populateBean之后invokeinitMethods之前public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {System.out.println("post bean before! :"+beanName); return bean; } @Override//invokeinitMethods之后public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {System.out.println("post bean after!"+beanName); return bean; }}
另一个重要的是:
InstantiationAwareBeanPostProcessor
文章图片
postProcessBeforeInstantiation调用时机:
文章图片
向上找调用者:
文章图片
继续向上:
文章图片
可以看出是在实例化之前:(也就是反射创建对象之前,如果postProcessBeforeInstantiation创建了一个非空的对象,则不会走实例化步骤。)
postProcessAfterInstantiation调用时机:
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {PropertyValues pvs = mbd.getPropertyValues(); if (bw == null) {if (!pvs.isEmpty()) {throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance"); }else {// Skip property population phase for null instance.return; }} // Give any InstantiationAwareBeanPostProcessors the opportunity to modify the// state of the bean before properties are set. This can be used, for example,// to support styles of field injection.boolean continueWithPropertyPopulation = true; if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {for (BeanPostProcessor bp : getBeanPostProcessors()) {if (bp instanceof InstantiationAwareBeanPostProcessor) {InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp; //在这里执行if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {continueWithPropertyPopulation = false; break; }}}} if (!continueWithPropertyPopulation) {return; } 省略。。。。。 applyPropertyValues(beanName, mbd, bw, pvs); }
可以看出是在在初始化之前,具体是属性填充之前。(初始化之前,实例化之后) 如果返回fales,则不会继续初始化,即不会属性填充。
postProcessPropertyValues调用时机:
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {PropertyValues pvs = mbd.getPropertyValues(); if (bw == null) {if (!pvs.isEmpty()) {throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance"); }else {// Skip property population phase for null instance.return; }} // Give any InstantiationAwareBeanPostProcessors the opportunity to modify the// state of the bean before properties are set. This can be used, for example,// to support styles of field injection.boolean continueWithPropertyPopulation = true; if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {for (BeanPostProcessor bp : getBeanPostProcessors()) {if (bp instanceof InstantiationAwareBeanPostProcessor) {InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp; if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {continueWithPropertyPopulation = false; break; }}}} if (!continueWithPropertyPopulation) {return; } if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME ||mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {MutablePropertyValues newPvs = new MutablePropertyValues(pvs); // Add property values based on autowire by name if applicable.if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME) {autowireByName(beanName, mbd, bw, newPvs); } // Add property values based on autowire by type if applicable.if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {autowireByType(beanName, mbd, bw, newPvs); } pvs = newPvs; } boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors(); boolean needsDepCheck = (mbd.getDependencyCheck() != RootBeanDefinition.DEPENDENCY_CHECK_NONE); if (hasInstAwareBpps || needsDepCheck) {PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching); if (hasInstAwareBpps) {for (BeanPostProcessor bp : getBeanPostProcessors()) {if (bp instanceof InstantiationAwareBeanPostProcessor) {InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp; pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName); if (pvs == null) {return; }}}}if (needsDepCheck) {checkDependencies(beanName, mbd, filteredPds, pvs); }} applyPropertyValues(beanName, mbd, bw, pvs); }
在postProcessAfterInstantiation之后,applyPropertyValues之前。(属性填充之前修改属性值)
总结: 执行顺序
- 1.postProcessBeforeInstantiation(实现这个方法可以做自定义实例化)
- 2.实例化
- 3.postProcessAfterInstantiation(是否要初始化)
- 4.postProcessPropertyValues(修改属性)
- 5.初始化(属性填充)(populateBean)
- 6.postProcesstBeforeInitialization( 自定义init方法执行之前)
- 7.invokeinitMethods(执行自定义的init方法)
- 8.postProcessAfterInitialization(自定义init方法执行之后)
文章图片
- 1.postProcessBeforeInstantiation(实现这个方法可以做自定义实例化)
- 2.实例化
- 3.postProcessAfterInstantiation(是否要初始化)
- 4.postProcessPropertyValues(修改属性)
- 5.初始化(属性填充)(populateBean)
- 6.postProcesstBeforeInitialization( 自定义init方法执行之前)
- 7.invokeAwareMethod
- 8.invokeinitMethods(执行自定义的init方法)
- 9.postProcessAfterInitialization(自定义init方法执行之后)
推荐阅读
- 热闹中的孤独
- Shell-Bash变量与运算符
- JS中的各种宽高度定义及其应用
- 2021-02-17|2021-02-17 小儿按摩膻中穴-舒缓咳嗽
- 深入理解Go之generate
- 异地恋中,逐渐适应一个人到底意味着什么()
- Activiti(一)SpringBoot2集成Activiti6
- 我眼中的佛系经纪人
- 《魔法科高中的劣等生》第26卷(Invasion篇)发售
- “成长”读书社群招募