概述
本文主要讲解下SpringBoot的一个关键扩展点BeanPostProcessor, 他有很多的子接口,这里我们一并做了一个介绍。
BeanPostProcessor家族介绍
BeanPostProcessor处理器分别在Bean生命周期的不同阶段起作用,Bean的实例化阶段先于Bean初始化阶段,最后是Bean的销毁阶段,主要规类如下:
Bean实例化阶段
在Spring Bean生命周期中,Bean实例化指的是创建Bean的过程, 此时Bean的属性还没有赋值。
1. InstantiationAwareBeanPostProcessor
作用: BeanPostProcessor的子接口,它可以在实例化之前回调,也可以在实例化之后但是属性设置或者自动装配发生之前回调。
使用场景: 可以用来修改特定Bean默认的实例化,比如创建代理类,或者实现额外的注册策略。
接口方法:
1). Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName)
- 在目标bean被实例化之前调用,返回值是Object类型,可以返回目标实例的一个代理用来代替目标实例。
- 返回值如果不是null, 后续不会再进行实例化,只会执行
postProcessAfterInitialization
这个回调,其他方法不调用。否则按照正常的流程走。
2). boolean postProcessAfterInstantiation(Object bean, String beanName)
- 在目标对象被实例化后并且属性值还没有被设置的时候调用。
- 返回值是boolean类型,返回true时,表示Bean属性需要被赋值;返回false表示跳过Bean属性赋值,并且InstantiationAwareBeanPostProcessor的postProcessProperties方法不会被调用。
3). PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName)
- 方法的作用在属性中被设置到目标实例之前调用,对属性值进行修改。
2. SmartInstantiationAwareBeanPostProcessor
作用: 继承于InstantiationAwareBeanPostProcessor
接口,主要作用也是在于目标对象的实例化过程中需要处理的事情。它是InstantiationAwareBeanPostProcessor接口的一个扩展。主要在Spring框架内部使用,不是重点。
接口方法:
1). Class predictBeanType(Class beanClass, String beanName)
- 用于预测Bean的类型,返回第一个预测成功的Class类型,如果不能预测返回null。主要在于BeanDefinition无法确定Bean类型的时候调用该方法来确定类型。
2). Constructor[] determineCandidateConstructors(Class beanClass, String beanName)
- 用于选择合适的构造器,比如类有多个构造器,可以实现这个方法选择合适的构造器并用于实例化对象。
- 该方法在
postProcessBeforeInstantiation
方法和postProcessAfterInstantiation方法之间调用,如果postProcessBeforeInstantiation
方法返回了一个新的实例代替了原本该生成的实例,那么该方法会被忽略。
3). Object getEarlyBeanReference(Object bean, String beanName)
getEarlyBeanReference
主要用于解决循环引用问题。比如ReferenceA实例内部有ReferenceB的引用,ReferenceB实例内部有ReferenceA的引用。首先先实例化ReferenceA,实例化完成之后提前把这个bean暴露在ObjectFactory中,然后populate属性,这个时候发现需要ReferenceB。然后去实例化ReferenceB,在实例化ReferenceB的时候它需要ReferenceA的实例才能继续,这个时候就会去ObjectFactory中找出了ReferenceA实例,ReferenceB顺利实例化。ReferenceB实例化之后,ReferenceA的populate属性过程也成功完成,注入了ReferenceB实例。提前把这个bean暴露在ObjectFactory中,这个ObjectFactory获取的实例就是通过getEarlyBeanReference方法得到的。
Bean初始化阶段
Bean初始化阶段是指Bean创建后,对其属性进行赋值(populate bean)、后置处理等操作的过程。
1. MergedBeanDefinitionPostProcessor
作用: 继承BeanPostProcessor, 在合并Bean定义之后调用。
接口方法:
1). postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName)
- 该方法是在合并Bean定义之后调用。
2. BeanPostProcessor
作用: 该方法是核心方法,主要是在Bean初始化前后调用。
接口方法:
1).Object postProcessBeforeInitialization(Object bean, String beanName)
- 在bean初始化之前调用的方法
2).Object postProcessAfterInitialization(Object bean, String beanName)
- 在bean初始化之后调用的方法
Bean销毁阶段
1. DestructionAwareBeanPostProcessor
作用: 继承BeanPostProcessor接口,Bean在容器被销毁之前调用
接口方法:
1).postProcessBeforeDestruction(Object bean, String beanName)
- bean在销毁之前调用
2).boolean requiresDestruction(Object bean)
- 在bean销毁之前调用,决定bean是否要被销毁
- 返回值未boolean类型,如果返回true,则先调用
postProcessBeforeDestruction
回调,如果返回false, 不进行销毁。
实战演练
- 定义Bean
@Data @Slf4j public class BeanLifeCycle { private String prop ; public BeanLifeCycle() { log.info("#################BeanLifeCycle 实例化"); } public void init() { log.info("#################BeanLifeCycle 初始化"); } public void destroy() { log.info("#################BeanLifeCycle 销毁"); } }
@Configuration public class LifeCycleConfig { @Bean(name = "beanLifeCycle", initMethod = "init", destroyMethod = "destroy") public BeanLifeCycle createBeanLifeCycle() { BeanLifeCycle beanLifeCycle = new BeanLifeCycle(); return beanLifeCycle; } }
- 创建
InstantiationAwareBeanPostProcessor
@Component @Slf4j public class TestInstantiationAwareBeanPostProcessor implements InstantiationAwareBeanPostProcessor { @Override public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException { if("beanLifeCycle".equals(beanName)) { log.info("################InstantiationAwareBeanPostProcessor before instant: [{}]", beanName); // 如果返回一个bean,则后续只会调用BeanPostProcessor的 postProcessAfterInitialization方法 //return new BeanLifeCycle().setProp("aaa"); } // 如果返回null,正常实例化 return null; } @Override public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException { if("beanLifeCycle".equals(beanName)) { log.info("################InstantiationAwareBeanPostProcessor after instant: bean: [{}], beanName: [{}]", bean, beanName); } // 返回true,表示Bean属性需要被赋值,否则不会 return true; } @Override public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException { if("beanLifeCycle".equals(beanName)) { log.info("################InstantiationAwareBeanPostProcessor postProcessProperties: pvs: [{}], bean: [{}], beanName: [{}]", pvs, bean, beanName); } return pvs; } }
- 创建普通的
BeanPostProcessor
@Component @Slf4j public class TestBeanPostProcessor implements BeanPostProcessor { @Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { if("beanLifeCycle".equals(beanName)) { log.info("################BeanPostProcessor before init: bean:[{}], beanName: [{}]", bean, beanName); } return bean; } @Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { if("beanLifeCycle".equals(beanName)) { log.info("################BeanPostProcessor after init: bean:[{}], beanName: [{}]", bean, beanName); } return bean; } }
- 创建
DestructionAwareBeanPostProcessor
@Slf4j @Component public class TestDestructionAwareBeanPostProcessor implements DestructionAwareBeanPostProcessor { @Override public void postProcessBeforeDestruction(Object obj, String beanName) throws BeansException { if("beanLifeCycle".equals(beanName)) { log.info("################DestructionAwareBeanPostProcessor before destroy: bean:[{}], beanName: [{}]", obj, beanName); } } @Override public boolean requiresDestruction(Object bean) { if(bean instanceof BeanLifeCycle) { log.info("################DestructionAwareBeanPostProcessor requiresDestruction: bean:[{}]", bean); } // true表示销毁, false表示不销毁,也不会执行postProcessBeforeDestruction方法了 return true; } }
- 执行结果
如图所示执行结果,得出结论如下:
InstantiationAwareBeanPostProcessor
是在类的实例化前后进行回调,如上图序号的1,3,4BeanPostProcessor
是在类的初始化前后进行回调,如上图中的5,7
源码解析
源码解析这块我们重点主要关注在InstantiationAwareBeanPostProcessor
和BeanPostProcessor
这两个相对比较中的扩展点。
以上的扩展接口都是围绕着Bean的创建,而Bean创建的入口AbstractAutowireCapableBeanFactory
的createBean
方法:
@Override protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException { if (logger.isTraceEnabled()) { logger.trace("Creating instance of bean '" + beanName + "'"); } RootBeanDefinition mbdToUse = mbd; // Make sure bean class is actually resolved at this point, and // clone the bean definition in case of a dynamically resolved Class // which cannot be stored in the shared merged bean definition. Class<?> resolvedClass = resolveBeanClass(mbd, beanName); if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) { mbdToUse = new RootBeanDefinition(mbd); mbdToUse.setBeanClass(resolvedClass); } // Prepare method overrides. try { mbdToUse.prepareMethodOverrides(); } catch (BeanDefinitionValidationException ex) { throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(), beanName, "Validation of method overrides failed", ex); } try { // resolveBeforeInstantiation方法主要是给InstantiationAwareBeanPostProcessor后置处理器一个Bean实例代理的机会. Object bean = resolveBeforeInstantiation(beanName, mbdToUse); // 如果返回的不为空,说明已经实例化了,则直接返回,为空的话,继续走下面的正常流程doCreateBean if (bean != null) { return bean; } } catch (Throwable ex) { throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName, "BeanPostProcessor before instantiation of bean failed", ex); } try { Object beanInstance = doCreateBean(beanName, mbdToUse, args); if (logger.isTraceEnabled()) { logger.trace("Finished creating instance of bean '" + beanName + "'"); } return beanInstance; } catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) { // A previously detected exception with proper bean creation context already, // or illegal singleton state to be communicated up to DefaultSingletonBeanRegistry. throw ex; } catch (Throwable ex) { throw new BeanCreationException( mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex); } }
参考上面源码中的注释,我们重点关注resolveBeforeInstantiation
方法。
@Nullable protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) { Object bean = null; // beforeInstantiationResolved属性值默认为false, 如果bean实例前置操作还未执行 if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) { // Make sure bean class is actually resolved at this point. // 判断是否有InstantiationAwareBeanPostProcessor处理器 if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) { Class<?> targetType = determineTargetType(beanName, mbd); if (targetType != null) { // 执行InstantiationAwareBeanPostProcessor处理器中的postProcessBeforeInstantiation方法 bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName); if (bean != null) { // 如果bean已经被上述的前置处理器实例化了, // 则跳过其他步骤,直接执行BeanPostProcessor处理器中的postProcessAfterInitialization方法进行初始化 bean = applyBeanPostProcessorsAfterInitialization(bean, beanName); } } } // 如果bean不为null,设置beforeInstantiationResolved属性值为true mbd.beforeInstantiationResolved = (bean != null); } return bean; }
如果没有对bean进行代理增量,返回null的情况,则走标准的流程,执行后面的doCreateBean
方法。
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException { // Instantiate the bean.实例化bean开始 BeanWrapper instanceWrapper = null; if (mbd.isSingleton()) { instanceWrapper = this.factoryBeanInstanceCache.remove(beanName); } if (instanceWrapper == null) { // 实例化bean instanceWrapper = createBeanInstance(beanName, mbd, args); } Object bean = instanceWrapper.getWrappedInstance(); Class<?> beanType = instanceWrapper.getWrappedClass(); if (beanType != NullBean.class) { mbd.resolvedTargetType = beanType; } // 实例化bean结束 // Allow post-processors to modify the merged bean definition. synchronized (mbd.postProcessingLock) { if (!mbd.postProcessed) { try { applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName); } catch (Throwable ex) { throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Post-processing of merged bean definition failed", ex); } mbd.postProcessed = true; } } // Eagerly cache singletons to be able to resolve circular references // even when triggered by lifecycle interfaces like BeanFactoryAware. boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences && isSingletonCurrentlyInCreation(beanName)); if (earlySingletonExposure) { if (logger.isTraceEnabled()) { logger.trace("Eagerly caching bean '" + beanName + "' to allow for resolving potential circular references"); } addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean)); } // Initialize the bean instance. Object exposedObject = bean; try { // 为bean属性赋值 populateBean(beanName, mbd, instanceWrapper); // 初始化bean exposedObject = initializeBean(beanName, exposedObject, mbd); } ....... }
重点关注这里的populateBean
和initializeBean
方法,后置处理器就是在这两个方法中起作用。
populateBean
方法代码如下:
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) { ..... // 获取所有的InstantiationAwareBeanPostProcessor if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) { for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) { // 调用postProcessAfterInstantiation方法,如果返回false, 则populateBean方法直接返回,后续赋值操作不再进行 if (!bp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) { return; } } } // 开始为属性赋值,比如@Autowired注解的 PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null); int resolvedAutowireMode = mbd.getResolvedAutowireMode(); if (resolvedAutowireMode == AUTOWIRE_BY_NAME || resolvedAutowireMode == AUTOWIRE_BY_TYPE) { MutablePropertyValues newPvs = new MutablePropertyValues(pvs); // Add property values based on autowire by name if applicable. if (resolvedAutowireMode == AUTOWIRE_BY_NAME) { autowireByName(beanName, mbd, bw, newPvs); } // Add property values based on autowire by type if applicable. if (resolvedAutowireMode == AUTOWIRE_BY_TYPE) { autowireByType(beanName, mbd, bw, newPvs); } pvs = newPvs; } boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors(); boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE); PropertyDescriptor[] filteredPds = null; if (hasInstAwareBpps) { if (pvs == null) { pvs = mbd.getPropertyValues(); } for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) { PropertyValues pvsToUse = bp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName); if (pvsToUse == null) { if (filteredPds == null) { filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching); } pvsToUse = bp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName); if (pvsToUse == null) { return; } } pvs = pvsToUse; } } if (needsDepCheck) { if (filteredPds == null) { filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching); } checkDependencies(beanName, mbd, filteredPds, pvs); } if (pvs != null) { applyPropertyValues(beanName, mbd, bw, pvs); } }
接着查看initializeBean
方法源码:
protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) { if (System.getSecurityManager() != null) { AccessController.doPrivileged((PrivilegedAction<Object>) () -> { invokeAwareMethods(beanName, bean); return null; }, getAccessControlContext()); } else { invokeAwareMethods(beanName, bean); } Object wrappedBean = bean; if (mbd == null || !mbd.isSynthetic()) { // 执行BeanPostProcessor的postProcessBeforeInitialization初始化前置处理器 wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName); } try { //执行初始化操作 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()) { // 执行BeanPostProcessor的postProcessBeforeInitialization初始化后置处理器 wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName); } return wrappedBean; }
上面我们通过源码的角度,针对关键的InstantiationAwareBeanPostProcessor
和BeanPostProcessor
两个接口做了一个分析,在源码阅读的时候,可以打上断点,一步一步调试,整体的一个执行流程如下图所示: