处理器继承关系
容器级处理器
BeanFactoryPostProcessor
public interface BeanFactoryPostProcessor {
/**
说明:
该接口方法是在Spring容器解析完配置文件注册了BeanDefinition之后,并在bean被实例化之前被调用的;
该接口方法定义在spring-bean模块中,但是并没有在IOC层被使用(如果要使用可以手动向BeanFactory注入该处理器),而是
在ApplicationContext层被调用,这意味着该处理器是用于在ApplicationContext层拓展而被定义的。
相关的应用:
1、CustomEditorConfigurer
配置自定义的属性编辑器时,会配置一个“org.springframework.beans.factory.config.CustomEditorConfigurer”的bean,
并给这个bean注入自定义的属性编辑器,CustomEditorConfigurer实现了BeanFactoryPostProcessor这个后处理器接口,因此
Spring会通过该处理器,在解析完后配置文件和实例化bean前,将我们自定义的属性编辑器添加到IOC容器中,这样便可以在后
面属性注入的时候使用我们自定义的属性编辑器了。
2、PropertyPlaceholderConfigurer
有时候,我们会在配置文件中使用占位符的方式来配置Bean,Spring在bean注入属性的时候会去解析这些占位符,该解析动作就
是通过PropertyPlaceholderConfigurer来实现的。PropertyPlaceholderConfigurer实现了BeanFactoryPostProcessor这个后处理器接口,在解析完后配置文件和实例化bean前,Spring会通过该处理器访问每个已经注册到容器的BeanDefinition对象,并替换${...}占位符。
另外,当我们配置了标签,Spring 就会自行注册了一个PropertyPlaceholderConfigurer的Bean,并且该Bean是一个处理器Bean。
3、CustomAutowireConfigurer
4、CustomScopeConfigurer
5、DeprecatedBeanWarner
*/
void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;
}
BeanDefinitionRegistryPostProcessor
public interface BeanDefinitionRegistryPostProcessor extends BeanFactoryPostProcessor {
/**
* Modify the application context's internal bean definition registry after its standard initialization.
* All regular bean definitions will have been loaded, but no beans will have been instantiated yet.
* This allows for adding further bean definitions before the next post-processing phase kicks in.
* 在标准初始化之后修改应用程序上下文的内部bean定义注册表。所有的常规bean定义都已经加载,但是还没有实例化bean。这允许
* 在下一个后处理阶段开始之前添加更多bean定义。
* @param registry the bean definition registry used by the application context
* @throws org.springframework.beans.BeansException in case of errors
说明:
BeanDefinitionRegistryPostProcessor接口继承自BeanFactoryPostProcessor接口,该处理器接口定义在spring-bean模块中,
但应用于ApplicationContext容器,即该处理器是为ApplicationContext容器扩展而被设计的,BeanFactoryPostProcessor处理器也
是为扩展而设计的,但是不同的是BeanFactoryPostProcessor可以通过在BeanFactory手工设置该处理器来执行处理器方法,而
BeanDefinitionRegistryPostProcessor即使在BeanFactory中手工设置也无法被被调用,必须在ApplicationContext中才能被调用;
该处理器方法的调用时间是在完成 BeanDefinition 注册后,实例化bean之前被调用的,该处理主要用于修改BeanDefinition注册表
信息,它用于被ApplicationContext调用,在bean注册到ioc后创建实例前修改bean定义和新增bean注册,这个是在context的refresh
方法调用。BeanDefinitionRegistryPostProcessor 的一个典型应用是扫描指定包及其子包下面拥有指定注解的类,你会发现在
BeanFactory中并没有使用到该后处理器,该后处理器为Spring容器扩展而设计的,IOC容器只加载一些常规的Bean配置,而像@Service、
@Repository、@Compent和@Bean等这些注解定义的Bean是ApplicationContext容器中才扩展出来的,其中
BeanDefinitionRegistryPostProcessor 有一个典型的应用是Mybatis中的@Mapper。此外,这里要注意的是@Service、@Repository、
@Compent和@Bean这些注解修饰的Bean并不是通过后处理器来注入的,而是通过自定义命名空间解析器来注入的。
相关的应用:
1、MapperScannerConfigurer
在mybatis集成spring的扩展包中(mybatis-spring-xxx.jar),就是通过MapperScannerConfigurer实现
BeanDefinitionRegistryPostProcessor接口的postProcessBeanDefinitionRegistry方法来实现扫描@Mapper注解修饰的接口,并向
BeanDefinition注册表中注册一系列的AnnotatedBeanDefinition对象,这样Spring就可以在后续的启动流程中向IOC容器注册Mapper
接口对象实例了,从而实现Mybatis与Spring的集成。另外,Mybatis中的那些Mapper接口,会通过动态代理的方式生成一个接口的
代理实例,从而完成一些持久化操作,这就是为什么Mybatis只需定义Mapper接口而不用实现类的原因;并且通过MapperScannerConfigurer
注入的AnnotatedBeanDefinition对象,在实例化完成后其Bean对象是一个Mybatis的MapperFactoryBean对象,该MapperFactoryBean
实现了Spring的FactoryBean接口,然后Spring容器在返回Mapper接口对象Bean的时候,就会通过FactoryBean接口来代理这个Mapper
接口,该代理操作会委托Mybatis自己来完成。总之,Mybatis集成Spring中的Mapper接口,其本质是一个MapperFactoryBean,
MapperFactoryBean实现了FactoryBean,所以每个Mapper对象在实例化的时候会调用FactoryBean#getObject()方法,创建一个Mapper
的实例。
*/
void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException;
}
Bean级处理器
BeanPostProcessor
// 该接口作用是:如果我们需要在Spring容器完成Bean的实例化,配置和其他的初始化后添加一些自己的逻辑处理,我们就可以定义一个或者多个BeanPostProcessor接口的实现
public interface BeanPostProcessor {
/**
1、BeanPostProcessor#postProcessBeforeInitialization
2、@PostConstruct修饰的方法
3、InitializingBean#afterPropertiesSet:设置完Bean的所有属性之后被调用
4、调用配置中的init-method方法
*/
Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;
/**
1、调用配置中的init-method方法
2、BeanPostProcessor#postProcessAfterInitialization:Bean执行初始化方法后被调用
3、@PreDestroy修饰的方法
4、DisposableBean#destroy:在bean被销毁的时候调用
5、调用配置中的destroy-method方法
*/
Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;
}
InstantiationAwareBeanPostProcessor
public interface InstantiationAwareBeanPostProcessor extends BeanPostProcessor {
/**
说明:
在调用bean构造函数实例化前被调用,IOC层在调用Bean构造器实例化之前会先执行该处理器方法,如果该处理器方法返回一个非
空对象,则IOC容器会中断后续初始化流程,即后续的属性注入也就不再执行了,直接返回该非空对象作为Bean的实例。
相关的应用:
1、AbstractAutoProxyCreator
Spring中的自动代理机制中就是通过该处理器方法来实现的,它通过扩展该处理器方法,在IOC层调用Bean构造器实例化之前会先
执行该处理器方法,并遍历所有的Bean判断这个Bean是否可以被代理(该实现机制是通过配置一个目标Bean与增强匹配的表达式
来现实的,如RegexpMethodPointcutAdvisor,并通过该表达式判断每个Bean是否存有对应的增强器,如果存在说明该bean可以被
自动代理),然后在 InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation 处理器方法中织入增强,并返
回代理后的代理类,返回代理类后IOC就直接返回该Bean实例了,后续的属性注入则无法再执行了。
*/
Object postProcessBeforeInstantiation(Class> beanClass, String beanName) throws BeansException;
// Spring调用构造器实例化Bean,然后将Bean包装为一个BeanWrapper后,并在所有的配置属性注入到Bean前该处理器方法被调用,
// 该处理器方法的返回值是一个Boolean值,它可以用来控制是否继续注入Bean属性
/**
说明:
Spring调用构造器实例化Bean,然后将Bean包装为一个BeanWrapper后,并在所有的配置属性注入到Bean前该处理器方法被调用,
该处理器方法的返回值是一个Boolean值,它可以用来控制是否继续注入Bean属性,在Spring源码中属性注入方法populateBean()
的执行步骤如下:
1、执行InstantiationAwareBeanPostProcessor处理器的postProcessAfterInstantiation方法,该函数可以控制程序是否继续
进行属性填充;
2、根据注入类型(byName/byType),提取依赖的bean,并统一存入PropertyValues中;
3、执行InstantiationAwareBeanPostProcessor#postProcessPropertyValues方法,属性获取完毕后,并在将PropertyValues注
入到Bean前对属性的再次处理,典型应用是requiredAnnotationBeanPostProcessor 类中对属性的验证;
4、将所有PropertyValues中的属性填充至BeanWrapper中。
相关的应用:
。。。
*/
boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException;
/**
说明:
该处理器方法是在BeanWrapper给Bean注入属性之前被调用的
相关的应用:
1、AutowiredAnnotationBeanPostProcessor
BeanWrapper在将给定的属性值注入到目标Bean之前,Spring会调用AutowiredAnnotationBeanPostProcessor#postProcessPropertyValues
处理器方法,将所有@Autowired注解修饰的依赖Bean注入到目标Bean,也就说由@Autowired注解修饰的Bean属性最先被注入到Bean中
2、RequiredAnnotationBeanPostProcessor
如果一个bean某些字段必须含有,则可以使用@Required注释,RequiredAnnotationBeanPostProcessor#postProcessPropertyValues
在所有属性注入到Bean前,回去检查所有被@Required注解修饰的方法(@Required只能修饰方法),判断是否有对应的属性注入。
如果任何带有@Required的属性未设置的话 将会抛出BeanInitializationException异常。
3、CommonAnnotationBeanPostProcessor
CommonAnnotationBeanPostProcessor通过扩展该处理器方法,将那些被@Resource注解修饰的属性注入到Bean
4、PersistenceAnnotationBeanPostProcessor执行@ PersistenceContext等JPA注解的注入
*/
PropertyValues postProcessPropertyValues(PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException;
}
SmartInstantiationAwareBeanPostProcessor
public interface SmartInstantiationAwareBeanPostProcessor extends InstantiationAwareBeanPostProcessor {
/** 在调用{@link InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation}前预测要返回bean的类型*/
Class> predictBeanType(Class> beanClass, String beanName) throws BeansException;
// 确定一个实例化时要用的构造器方法
Constructor>[] determineCandidateConstructors(Class> beanClass, String beanName) throws BeansException;
/**
该方法用于返回早期的Bean引用,即半成品的Bean,已经实例化但是还没有注入属性
比如:CircularityA引用CircularityB,CircularityB引用CircularityC,CircularityC引用CircularityA
(1)Spring容器创建单例“circularityA” Bean:首先依据无參构造器创建“circularityA”Bean, 并暴露一个ObjectFactory,
这个ObjectFactory用于返回提前暴露的circularityA,然后将“circularityA”放到“当前创建的Bean缓存池”中。
然后进行setter注入“circularityB”;
(2)Spring容器创建单例“circularityB” Bean:首先依据无參构造器创建“circularityB" Bean,并暴露一个ObjectFactory,
于返回提前暴露的circularityB。然后将 circularityB 放入“当前创建的Bean缓存池”中,然后进行setter注入 circularityC ;
(3)Spring容器创建单例“circularityC” Bean:首先依据无參构造器创建“circularityC”Bean,并暴露一个ObjectFactory,
用于返回提前暴露的circularityC。并将 circularityC 放入“当前创建的Bean缓存池”中, 然后进行setter注入 circularityA ;
进行注入“circularityA”时因为步骤(1)提前暴露了 circularityA 所以从之前的Cache里面拿BeanA,而不用反复创建。
(4)最后在依赖注入“circularityB”和“circularityA”也是从catch里面拿提前暴露的bean。 完毕setter注入。
该方法中,如果入参bean是 circularityA 这个Bean,则在第一次创建circularityA时会返回一个半成品的Bean,已经实例化但
是还没有注入属性,我们称这个半成品的bean为exposedObject,即早期暴露的Bean。当circularityC创建时,会先注入这个半成品
beanA,这样就先完成了BeanC的创建,接着会完成BeanC的创建,到最后BeanA时,BeanC已经完成了创建,所以BeanA也就可以顺利完
成。
此外,对于“prototype”作用域Bean。Spring容器无法完毕依赖注入,由于“prototype”作用域的Bean,Spring容器不进行缓
存,因此无法提前暴露一个创建中的Bean。
还有就是,构造函数循环依赖注入时,也会抛异常。
*/
Object getEarlyBeanReference(Object bean, String beanName) throws BeansException;
}
MergedBeanDefinitionPostProcessor
public interface MergedBeanDefinitionPostProcessor extends BeanPostProcessor {
// BeanDefinition 被包装为 BeanWrapper 后,会调用该方法;典型的应用是将自动装配@Autowired注解修饰的属性保存到RootBeanDefinition#externallyManagedConfigMembers方便后续注入到Bean实例
void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class> beanType, String beanName);
}
该处理在BeanFactory#doCreateBean的运用场景(常规Bean创建的执行步骤)如下:
//步骤一:实例化bean,将 BeanDefinition 转换为 BeanWrapper
// 这里是创建bean的地方,由createBeanInstance方法来完成,根据指定bean使用相应的策略(如:工厂方法、构造函数自动注入、简单初始化)创建实例
instanceWrapper = createBeanInstance(beanName, mbd, args);
//步骤二:MergedBeanDefinitionPostProcessor 的应用
applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
//步骤三:依赖处理(会应用SmartInstantiationAwareBeanPostProcessor处理器)
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences && isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
// 为避免后期循环依赖,bean初始化完成前将创建实例的ObjectFactory加入缓存:
addSingletonFactory(beanName, new ObjectFactory
补充说明
InstantiationAwareBeanPostProcessor、DestructionAwareBeanPostProcessor这两个分别是Bean在初始化和销毁之前的回调方法
SmartInstantiationAwareBeanPostProcessor这个相当于InstantiationAwareBeanPostProcessor的扩展版本,增加了一个对Bean类型预测的回调,但这个主要是Spring框架内部用的,用户还是用InstantiationAwareBeanPostProcessor即可
MergedBeanDefinitionPostProcessor则是在合并处理Bean定义的时候的回调。这个东东按我的理解也基本是框架内部使用的,用户不用管