本章目的
认识SpringBPP,掌握BeanPostProcessor。
本章可能会有些枯燥,客官可以直接看最下面的总结。
系统版本
- jdk1.8
- springboot 2.1.6.RELEASE
- 开发工具(IntelliJ IDEA 2018.1.5 x64)
- apache maven(3.6.0,本章采用maven形式管理jar包,具体配置环境变量以及使用请自行查找资料)
开始。。。
在spring世界中,当我们要对bean的实例化,初始化过程中做点什么的时候,作为开发人员,显然不需要继承ApplicationContext或者BeanFactory,这个时候,bpp提供对外的钩子,就被派上用场了。下面我们介绍几个比较常见的bpp接口。
1. BeanFactoryPostProcessor
@FunctionalInterface public interface BeanFactoryPostProcessor { /** * Modify the application context's internal bean factory after its standard * initialization. All bean definitions will have been loaded, but no beans * will have been instantiated yet. This allows for overriding or adding * properties even to eager-initializing beans. * @param beanFactory the bean factory used by the application context * @throws org.springframework.beans.BeansException in case of errors */ void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException; }
实现该接口,可以在spring的bean创建之前,修改bean的定义属性。也就是说,Spring允许BeanFactoryPostProcessor在容器实例化任何其它bean之前读取配置元数据,并可以根据需要进行修改,例如可以把bean的scope从singleton改为prototype,也可以把property的值给修改掉。可以同时配置多个BeanFactoryPostProcessor,并通过设置’order’属性来控制各个BeanFactoryPostProcessor的执行次序。
注意:BeanFactoryPostProcessor是在spring容器加载了bean的定义文件之后,在bean实例化之前执行的。接口方法的入参是ConfigurrableListableBeanFactory,使用该参数,可以获取到相关bean的定义信息
spring中,有内置的一些BeanFactoryPostProcessor实现类,常用的有:
- org.springframework.beans.factory.config.PropertyPlaceholderConfigurer:${}属性覆盖
- org.springframework.beans.factory.config.PropertyOverrideConfigurer
- org.springframework.beans.factory.config.CustomEditorConfigurer:用来注册自定义的属性编辑器
2. BeanPostProcessor :bean的后置处理器
public interface BeanPostProcessor { /** * Apply this BeanPostProcessor to the given new bean instance <i>before</i> any bean * initialization callbacks (like InitializingBean's {@code afterPropertiesSet} * or a custom init-method). The bean will already be populated with property values. * The returned bean instance may be a wrapper around the original. * <p>The default implementation returns the given {@code bean} as-is. * @param bean the new bean instance * @param beanName the name of the bean * @return the bean instance to use, either the original or a wrapped one; * if {@code null}, no subsequent BeanPostProcessors will be invoked * @throws org.springframework.beans.BeansException in case of errors * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet */ @Nullable default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { return bean; } /** * Apply this BeanPostProcessor to the given new bean instance <i>after</i> any bean * initialization callbacks (like InitializingBean's {@code afterPropertiesSet} * or a custom init-method). The bean will already be populated with property values. * The returned bean instance may be a wrapper around the original. * <p>In case of a FactoryBean, this callback will be invoked for both the FactoryBean * instance and the objects created by the FactoryBean (as of Spring 2.0). The * post-processor can decide whether to apply to either the FactoryBean or created * objects or both through corresponding {@code bean instanceof FactoryBean} checks. * <p>This callback will also be invoked after a short-circuiting triggered by a * {@link InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation} method, * in contrast to all other BeanPostProcessor callbacks. * <p>The default implementation returns the given {@code bean} as-is. * @param bean the new bean instance * @param beanName the name of the bean * @return the bean instance to use, either the original or a wrapped one; * if {@code null}, no subsequent BeanPostProcessors will be invoked * @throws org.springframework.beans.BeansException in case of errors * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet * @see org.springframework.beans.factory.FactoryBean */ @Nullable default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { return bean; }
BeanPostProcessor,可以在spring容器实例化bean之后,在执行bean的初始化方法前后,添加一些自己的处理逻辑。这里说的初始化方法,指的是下面两种:
- bean实现了InitializingBean接口,对应的方法为afterPropertiesSet
- 在bean定义的时候,通过init-method设置的方法
注意:BeanPostProcessor是在spring容器加载了bean的定义文件并且实例化bean之后执行的。BeanPostProcessor的执行顺序是在BeanFactoryPostProcessor之后。 postProcessBeforeInitialization 是在bean实例化之前,属性设置之后但是初始化之前
pstProcessAfterInitialization是在所有初始化方法之后
这个接口很重要,所以 接下来,我们重点介绍下这个接口。先看下 他的继承关系。
继承实现关系
从图中可以看出,BeanPostProcessor的实现类有很多,我们从左向右挑几个比较常用的:1). DestructionAwareBeanPostProcessor :销毁Bean后置处理器
public interface DestructionAwareBeanPostProcessor extends BeanPostProcessor { /** * Apply this BeanPostProcessor to the given bean instance before its * destruction, e.g. invoking custom destruction callbacks. ... */ void postProcessBeforeDestruction(Object bean, String beanName) throws BeansException; /** * Determine whether the given bean instance requires destruction by this * post-processor. * <p>The default implementation returns {@code true}. ... */ default boolean requiresDestruction(Object bean) { return true; } } 注释已经很清楚了,就是销毁bean之前,你还想做什么。
2). MergedBeanDefinitionPostProcessor :合并Bean定义后置处理器
public interface MergedBeanDefinitionPostProcessor extends BeanPostProcessor { /** * Post-process the given merged bean definition for the specified bean. ... */ void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName); /** * A notification that the bean definition for the specified name has been reset, * and that this post-processor should clear any metadata for the affected bean. ... */ default void resetBeanDefinition(String beanName) { } }
合并Bean定义后置处理器,感觉 概念很模糊。大家可以看下,它的一个实现类AutuwiredAnnotationBeanPostProcessor
//在每个bean实例化后,初始化前执行,获取并记录该bean属性注入的元数据(成员),在随后的属性注入时使用 @Override public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) { InjectionMetadata metadata = findAutowiringMetadata(beanName, beanType, null); metadata.checkConfigMembers(beanDefinition); }
这个方法,检查并注册需要注入的成员,然后调用InstantiationAwareBeanPostProcessor#postProcessProperties方法,完成所有成员的属性注入(依赖注入)
@Override public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) { InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs); try { metadata.inject(bean, beanName, pvs); } catch (BeanCreationException ex) { throw ex; } catch (Throwable ex) { throw new BeanCreationException(beanName, "Injection of autowired dependencies failed", ex); } return pvs; }
3). InstantiationAwareBeanPostProcessor :实例化bean后置处理器
public interface InstantiationAwareBeanPostProcessor extends BeanPostProcessor { /** * Apply this BeanPostProcessor <i>before the target bean gets instantiated</i>. * The returned bean object may be a proxy to use instead of the target bean, * effectively suppressing default instantiation of the target bean. * <p>If a non-null object is returned by this method, the bean creation process * will be short-circuited. The only further processing applied is the ... 调用机制为bean实例化(Instantiation)之前 默认null,即什么不做,代表走默认实例化。 如果返回了bean实例, 则会替代原来正常通过target bean生成的bean的流程. 典型的例如aop返回proxy对象. */ @Nullable default Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException { return null; } /** * Perform operations after the bean has been instantiated, via a constructor or factory method, * but before Spring property population (from explicit properties or autowiring) occurs. ... //调用时机为bean实例化(Instantiation)之后和任何初始化(Initialization)之前。 //实例化完了之后,如果这里返回true,代表这个bean的属性会被正常set进去,如果是fa//lse,那么就会跳过,spring给的建议是一般都要返回true。 */ default boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException { return true; } /** * Post-process the given property values before the factory applies them * to the given bean, without any need for property descriptors. * <p>Implementations should return {@code null} (the default) if they provide a custom * {@link #postProcessPropertyValues} implementation, and {@code pvs} otherwise. * In a future version of this interface (with {@link #postProcessPropertyValues} removed), * the default implementation will return the given {@code pvs} as-is directly. ... //调用时机为postProcessAfterInstantiation执行之后并返回true, //返回的PropertyValues将作用于给定bean属性赋值. //spring 5.1之后出现以替换@Deprecated标注的postProcessPropertyValues */ @Nullable default PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException { return null; } /** * Post-process the given property values before the factory applies them * to the given bean. Allows for checking whether all dependencies have been * satisfied, for example based on a "Required" annotation on bean property setters. * <p>Also allows for replacing the property values to apply, typically through * creating a new MutablePropertyValues instance based on the original PropertyValues, * adding or removing specific values. * <p>The default implementation returns the given {@code pvs} as-is. ... */ @Deprecated @Nullable default PropertyValues postProcessPropertyValues( PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException { return pvs; }
4). SmartInstantiationAwareBeanPostProcessor :智能实例化bean后置处理器(InstantiationAwareBeanPostProcessor的子类)
public interface SmartInstantiationAwareBeanPostProcessor extends InstantiationAwareBeanPostProcessor { /** * Predict the type of the bean to be eventually returned from this * processor's {@link #postProcessBeforeInstantiation} callback. * <p>The default implementation returns {@code null}. ... //预测Bean的类型,返回第一个预测成功的Class类型,如果不能预测返回null */ @Nullable default Class<?> predictBeanType(Class<?> beanClass, String beanName) throws BeansException { return null; } /** * Determine the candidate constructors to use for the given bean. * <p>The default implementation returns {@code null}. ... // 选择合适的构造器,比如目标对象有多个构造器,在这里可以进行一些定制化,选择合适的构造器 // beanClass参数表示目标实例的类型,beanName是目标实例在Spring容器中的name // 返回值是个构造器数组,如果返回null,会执行下一个PostProcessor的determineCandidateConstructors方法;否则选取该PostProcessor选择的构造器 */ @Nullable default Constructor<?>[] determineCandidateConstructors(Class<?> beanClass, String beanName) throws BeansException { return null; } /** * Obtain a reference for early access to the specified bean, * typically for the purpose of resolving a circular reference. * <p>This callback gives post-processors a chance to expose a wrapper * early - that is, before the target bean instance is fully initialized. * The exposed object should be equivalent to the what * {@link #postProcessBeforeInitialization} / {@link #postProcessAfterInitialization} * would expose otherwise. Note that the object returned by this method will * be used as bean reference unless the post-processor returns a different * wrapper from said post-process callbacks. In other words: Those post-process * callbacks may either eventually expose the same reference or alternatively * return the raw bean instance from those subsequent callbacks (if the wrapper * for the affected bean has been built for a call to this method already, * it will be exposes as final bean reference by default). * <p>The default implementation returns the given {@code bean} as-is. ... //获得提前暴露的bean引用。主要用于解决循环引用的问题 //只有单例对象才会调用此方法 */ default Object getEarlyBeanReference(Object bean, String beanName) throws BeansException { return bean; } }
可以看出继承InstantiationAwareBeanPostProcessor接口,多了三个方法。这个接口,有一个比较厉害的实现类AbstractAutoProxyCreator,它是AOP实现的核心。在下一个系列中,我们再细说这个类。
3. AbstractAutowireCapableBeanFactory :BeanPostProcessor的入口,spring世界中的生产者
类中方法调用顺序
/** * Abstract bean factory superclass that implements default bean creation, * with the full capabilities specified by the {@link RootBeanDefinition} class. * Implements the {@link org.springframework.beans.factory.config.AutowireCapableBeanFactory} * interface in addition to AbstractBeanFactory's {@link #createBean} method. * * <p>Provides bean creation (with constructor resolution), property population, * wiring (including autowiring), and initialization. Handles runtime bean * references, resolves managed collections, calls initialization methods, etc. * Supports autowiring constructors, properties by name, and properties by type. * * <p>The main template method to be implemented by subclasses is * {@link #resolveDependency(DependencyDescriptor, String, Set, TypeConverter)}, * used for autowiring by type. In case of a factory which is capable of searching * its bean definitions, matching beans will typically be implemented through such * a search. For other factory styles, simplified matching algorithms can be implemented. * * <p>Note that this class does <i>not</i> assume or implement bean definition * registry capabilities. See {@link DefaultListableBeanFactory} for an implementation * of the {@link org.springframework.beans.factory.ListableBeanFactory} and * {@link BeanDefinitionRegistry} interfaces, which represent the API and SPI * view of such a factory, respectively. ... */ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory implements AutowireCapableBeanFactory { /** * Central method of this class: creates a bean instance, * populates the bean instance, applies post-processors, etc. * @see #doCreateBean */ @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 { // Give BeanPostProcessors a chance to return a proxy instead of the target bean instance. //bean的实例化后前置处理器,如果有,这里会返回代理的实例。AOP的实现基础就是基于这里来实现的 Object bean = resolveBeforeInstantiation(beanName, mbdToUse); //如果不为空 直接返回 修饰后的实例,并中断主线 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); } } ... /** * Populate the bean instance in the given BeanWrapper with the property values * from the bean definition. * @param beanName the name of the bean * @param mbd the bean definition for the bean * @param bw the BeanWrapper with bean instance */ @SuppressWarnings("deprecation") // for postProcessPropertyValues protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) { if (bw == null) { if (mbd.hasPropertyValues()) { 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; //BeanDefinition为应用程序bean,而非基础框架bean信息 //注册过InstantiationAwareBeanPostProcessor类型接口 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; } PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null); //ioc依赖注入 if (mbd.getResolvedAutowireMode() == AUTOWIRE_BY_NAME || mbd.getResolvedAutowireMode() == AUTOWIRE_BY_TYPE) { MutablePropertyValues newPvs = new MutablePropertyValues(pvs); // Add property values based on autowire by name if applicable. if (mbd.getResolvedAutowireMode() == AUTOWIRE_BY_NAME) { autowireByName(beanName, mbd, bw, newPvs); } // Add property values based on autowire by type if applicable. if (mbd.getResolvedAutowireMode() == AUTOWIRE_BY_TYPE) { autowireByType(beanName, mbd, bw, newPvs); } pvs = newPvs; } //容器是否注册了InstantiationAwareBeanPostProcessor boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors(); // 是否进行依赖检查 boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE); PropertyDescriptor[] filteredPds = null; if (hasInstAwareBpps) { if (pvs == null) { pvs = mbd.getPropertyValues(); } for (BeanPostProcessor bp : getBeanPostProcessors()) { if (bp instanceof InstantiationAwareBeanPostProcessor) { InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp; PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName); if (pvsToUse == null) { if (filteredPds == null) { filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching); } pvsToUse = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName); if (pvsToUse == null) { return; } } pvs = pvsToUse; } } } if (needsDepCheck) { if (filteredPds == null) { filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching); } // 检查是否满足相关依赖关系,对应的depends-on属性,需要确保所有依赖的Bean先完成初始化 checkDependencies(beanName, mbd, filteredPds, pvs); } if (pvs != null) { //将pvs上所有的属性填充到BeanWrapper对应的Bean实例中 applyPropertyValues(beanName, mbd, bw, pvs); } } }
总结
- BPP是Spring container的一个扩展,在容器初始化bean的过程过,对每个bean都会执行一次,是容器本身的回调行为。ApplicationContext和BeanFactory,处理BPP的时候,有些区别。感兴趣的同学可以看下相关文章。
- BeanPostProcessor调用机制为 spring容器实例化bean之后,在执行bean的初始化方法前后。
- MergedBeanDefinitionPostProcessor、InstantiationAwareBeanPostProcessor都继承自BeanPostProcessor但是,调用机制不太一样。InstantiationAwareBeanPostProcessor为bean实例化前后,MergedBeanDefinitionPostProcessor为bean实例化后,初始化前执行。
- BeanFactoryPostProcessor是在spring容器加载了bean的定义文件之后,在bean实例化之前执行的。
这篇文章写起来,很枯燥,很吃力,参考了一些大神的博客,spring官网的文档,加上自己对源码的理解,断断续续大概用了一天的时间,如果有问题,欢迎大家在下方指摘。谢谢!
本来打算这篇文章把上一篇文章提到的问题一次性讲了,但是 背后的东西容太多了,下一篇我们实战下,搞点轻松加愉快的!
参考内容:
- https://blog.csdn.net/caihaijiang/article/details/35552859
- https://m.jb51.net/article/139531.htm
- https://spring.io/projects/spring-boot/