處理器繼承關(guān)系
image.png
容器級(jí)處理器
BeanFactoryPostProcessor
public interface BeanFactoryPostProcessor {
/**
說明:
該接口方法是在Spring容器解析完配置文件注冊了BeanDefinition之后盾碗,并在bean被實(shí)例化之前被調(diào)用的诅病;
該接口方法定義在spring-bean模塊中益缠,但是并沒有在IOC層被使用(如果要使用可以手動(dòng)向BeanFactory注入該處理器),而是
在ApplicationContext層被調(diào)用,這意味著該處理器是用于在ApplicationContext層拓展而被定義的。
相關(guān)的應(yīng)用:
1、CustomEditorConfigurer
配置自定義的屬性編輯器時(shí)蘑秽,會(huì)配置一個(gè)“org.springframework.beans.factory.config.CustomEditorConfigurer”的bean饺著,
并給這個(gè)bean注入自定義的屬性編輯器,CustomEditorConfigurer實(shí)現(xiàn)了BeanFactoryPostProcessor這個(gè)后處理器接口肠牲,因此
Spring會(huì)通過該處理器幼衰,在解析完后配置文件和實(shí)例化bean前,將我們自定義的屬性編輯器添加到IOC容器中缀雳,這樣便可以在后
面屬性注入的時(shí)候使用我們自定義的屬性編輯器了渡嚣。
2、PropertyPlaceholderConfigurer
有時(shí)候肥印,我們會(huì)在配置文件中使用占位符的方式來配置Bean识椰,Spring在bean注入屬性的時(shí)候會(huì)去解析這些占位符,該解析動(dòng)作就
是通過PropertyPlaceholderConfigurer來實(shí)現(xiàn)的深碱。PropertyPlaceholderConfigurer實(shí)現(xiàn)了BeanFactoryPostProcessor這個(gè)后處理器接口腹鹉,在解析完后配置文件和實(shí)例化bean前,Spring會(huì)通過該處理器訪問每個(gè)已經(jīng)注冊到容器的BeanDefinition對(duì)象敷硅,并替換${...}占位符功咒。
另外,當(dāng)我們配置了<property-placeholder>標(biāo)簽绞蹦,Spring 就會(huì)自行注冊了一個(gè)PropertyPlaceholderConfigurer的Bean力奋,并且該Bean是一個(gè)處理器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.
* 在標(biāo)準(zhǔn)初始化之后修改應(yīng)用程序上下文的內(nèi)部bean定義注冊表澡屡。所有的常規(guī)bean定義都已經(jīng)加載滨彻,但是還沒有實(shí)例化bean。這允許
* 在下一個(gè)后處理階段開始之前添加更多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模塊中休偶,
但應(yīng)用于ApplicationContext容器梁厉,即該處理器是為ApplicationContext容器擴(kuò)展而被設(shè)計(jì)的,BeanFactoryPostProcessor處理器也
是為擴(kuò)展而設(shè)計(jì)的踏兜,但是不同的是BeanFactoryPostProcessor可以通過在BeanFactory手工設(shè)置該處理器來執(zhí)行處理器方法词顾,而
BeanDefinitionRegistryPostProcessor即使在BeanFactory中手工設(shè)置也無法被被調(diào)用,必須在ApplicationContext中才能被調(diào)用碱妆;
該處理器方法的調(diào)用時(shí)間是在完成 BeanDefinition 注冊后肉盹,實(shí)例化bean之前被調(diào)用的,該處理主要用于修改BeanDefinition注冊表
信息疹尾,它用于被ApplicationContext調(diào)用上忍,在bean注冊到ioc后創(chuàng)建實(shí)例前修改bean定義和新增bean注冊骤肛,這個(gè)是在context的refresh
方法調(diào)用。BeanDefinitionRegistryPostProcessor 的一個(gè)典型應(yīng)用是掃描指定包及其子包下面擁有指定注解的類窍蓝,你會(huì)發(fā)現(xiàn)在
BeanFactory中并沒有使用到該后處理器腋颠,該后處理器為Spring容器擴(kuò)展而設(shè)計(jì)的,IOC容器只加載一些常規(guī)的Bean配置吓笙,而像@Service淑玫、
@Repository、@Compent和@Bean等這些注解定義的Bean是ApplicationContext容器中才擴(kuò)展出來的面睛,其中
BeanDefinitionRegistryPostProcessor 有一個(gè)典型的應(yīng)用是Mybatis中的@Mapper絮蒿。此外,這里要注意的是@Service叁鉴、@Repository土涝、
@Compent和@Bean這些注解修飾的Bean并不是通過后處理器來注入的,而是通過自定義命名空間解析器來注入的亲茅。
相關(guān)的應(yīng)用:
1回铛、MapperScannerConfigurer
在mybatis集成spring的擴(kuò)展包中(mybatis-spring-xxx.jar),就是通過MapperScannerConfigurer實(shí)現(xiàn)
BeanDefinitionRegistryPostProcessor接口的postProcessBeanDefinitionRegistry方法來實(shí)現(xiàn)掃描@Mapper注解修飾的接口克锣,并向
BeanDefinition注冊表中注冊一系列的AnnotatedBeanDefinition對(duì)象茵肃,這樣Spring就可以在后續(xù)的啟動(dòng)流程中向IOC容器注冊Mapper
接口對(duì)象實(shí)例了,從而實(shí)現(xiàn)Mybatis與Spring的集成袭祟。另外验残,Mybatis中的那些Mapper接口,會(huì)通過動(dòng)態(tài)代理的方式生成一個(gè)接口的
代理實(shí)例巾乳,從而完成一些持久化操作您没,這就是為什么Mybatis只需定義Mapper接口而不用實(shí)現(xiàn)類的原因;并且通過MapperScannerConfigurer
注入的AnnotatedBeanDefinition對(duì)象胆绊,在實(shí)例化完成后其Bean對(duì)象是一個(gè)Mybatis的MapperFactoryBean對(duì)象氨鹏,該MapperFactoryBean
實(shí)現(xiàn)了Spring的FactoryBean接口,然后Spring容器在返回Mapper接口對(duì)象Bean的時(shí)候压状,就會(huì)通過FactoryBean接口來代理這個(gè)Mapper
接口仆抵,該代理操作會(huì)委托Mybatis自己來完成≈侄總之镣丑,Mybatis集成Spring中的Mapper接口,其本質(zhì)是一個(gè)MapperFactoryBean娱两,
MapperFactoryBean實(shí)現(xiàn)了FactoryBean莺匠,所以每個(gè)Mapper對(duì)象在實(shí)例化的時(shí)候會(huì)調(diào)用FactoryBean#getObject()方法,創(chuàng)建一個(gè)Mapper
的實(shí)例十兢。
*/
void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException;
}
Bean級(jí)處理器
BeanPostProcessor
// 該接口作用是:如果我們需要在Spring容器完成Bean的實(shí)例化趣竣,配置和其他的初始化后添加一些自己的邏輯處理摇庙,我們就可以定義一個(gè)或者多個(gè)BeanPostProcessor接口的實(shí)現(xiàn)
public interface BeanPostProcessor {
/**
1、BeanPostProcessor#postProcessBeforeInitialization
2期贫、@PostConstruct修飾的方法
3跟匆、InitializingBean#afterPropertiesSet:設(shè)置完Bean的所有屬性之后被調(diào)用
4、調(diào)用<bean>配置中的init-method方法
*/
Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;
/**
1通砍、調(diào)用<bean>配置中的init-method方法
2玛臂、BeanPostProcessor#postProcessAfterInitialization:Bean執(zhí)行初始化方法后被調(diào)用
3、@PreDestroy修飾的方法
4封孙、DisposableBean#destroy:在bean被銷毀的時(shí)候調(diào)用
5迹冤、調(diào)用<bean>配置中的destroy-method方法
*/
Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;
}
InstantiationAwareBeanPostProcessor
public interface InstantiationAwareBeanPostProcessor extends BeanPostProcessor {
/**
說明:
在調(diào)用bean構(gòu)造函數(shù)實(shí)例化前被調(diào)用,IOC層在調(diào)用Bean構(gòu)造器實(shí)例化之前會(huì)先執(zhí)行該處理器方法虎忌,如果該處理器方法返回一個(gè)非
空對(duì)象泡徙,則IOC容器會(huì)中斷后續(xù)初始化流程,即后續(xù)的屬性注入也就不再執(zhí)行了膜蠢,直接返回該非空對(duì)象作為Bean的實(shí)例堪藐。
相關(guān)的應(yīng)用:
1、AbstractAutoProxyCreator
Spring中的自動(dòng)代理機(jī)制中就是通過該處理器方法來實(shí)現(xiàn)的挑围,它通過擴(kuò)展該處理器方法礁竞,在IOC層調(diào)用Bean構(gòu)造器實(shí)例化之前會(huì)先
執(zhí)行該處理器方法,并遍歷所有的Bean判斷這個(gè)Bean是否可以被代理(該實(shí)現(xiàn)機(jī)制是通過配置一個(gè)目標(biāo)Bean與增強(qiáng)匹配的表達(dá)式
來現(xiàn)實(shí)的杉辙,如RegexpMethodPointcutAdvisor模捂,并通過該表達(dá)式判斷每個(gè)Bean是否存有對(duì)應(yīng)的增強(qiáng)器,如果存在說明該bean可以被
自動(dòng)代理)蜘矢,然后在 InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation 處理器方法中織入增強(qiáng)狂男,并返
回代理后的代理類,返回代理類后IOC就直接返回該Bean實(shí)例了品腹,后續(xù)的屬性注入則無法再執(zhí)行了岖食。
*/
Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException;
// Spring調(diào)用構(gòu)造器實(shí)例化Bean,然后將Bean包裝為一個(gè)BeanWrapper后舞吭,并在所有的配置屬性注入到Bean前該處理器方法被調(diào)用县耽,
// 該處理器方法的返回值是一個(gè)Boolean值,它可以用來控制是否繼續(xù)注入Bean屬性
/**
說明:
Spring調(diào)用構(gòu)造器實(shí)例化Bean镣典,然后將Bean包裝為一個(gè)BeanWrapper后,并在所有的配置屬性注入到Bean前該處理器方法被調(diào)用唾琼,
該處理器方法的返回值是一個(gè)Boolean值兄春,它可以用來控制是否繼續(xù)注入Bean屬性,在Spring源碼中屬性注入方法populateBean()
的執(zhí)行步驟如下:
1锡溯、執(zhí)行InstantiationAwareBeanPostProcessor處理器的postProcessAfterInstantiation方法赶舆,該函數(shù)可以控制程序是否繼續(xù)
進(jìn)行屬性填充哑姚;
2、根據(jù)注入類型(byName/byType)芜茵,提取依賴的bean叙量,并統(tǒng)一存入PropertyValues中;
3九串、執(zhí)行InstantiationAwareBeanPostProcessor#postProcessPropertyValues方法绞佩,屬性獲取完畢后,并在將PropertyValues注
入到Bean前對(duì)屬性的再次處理猪钮,典型應(yīng)用是requiredAnnotationBeanPostProcessor 類中對(duì)屬性的驗(yàn)證品山;
4、將所有PropertyValues中的屬性填充至BeanWrapper中烤低。
相關(guān)的應(yīng)用:
肘交。。扑馁。
*/
boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException;
/**
說明:
該處理器方法是在BeanWrapper給Bean注入屬性之前被調(diào)用的
相關(guān)的應(yīng)用:
1涯呻、AutowiredAnnotationBeanPostProcessor
BeanWrapper在將給定的屬性值注入到目標(biāo)Bean之前,Spring會(huì)調(diào)用AutowiredAnnotationBeanPostProcessor#postProcessPropertyValues
處理器方法腻要,將所有@Autowired注解修飾的依賴Bean注入到目標(biāo)Bean复罐,也就說由@Autowired注解修飾的Bean屬性最先被注入到Bean中
2、RequiredAnnotationBeanPostProcessor
如果一個(gè)bean某些字段必須含有闯第,則可以使用@Required注釋市栗,RequiredAnnotationBeanPostProcessor#postProcessPropertyValues
在所有屬性注入到Bean前,回去檢查所有被@Required注解修飾的方法(@Required只能修飾方法)咳短,判斷是否有對(duì)應(yīng)的屬性注入填帽。
如果任何帶有@Required的屬性未設(shè)置的話 將會(huì)拋出BeanInitializationException異常。
3咙好、CommonAnnotationBeanPostProcessor
CommonAnnotationBeanPostProcessor通過擴(kuò)展該處理器方法篡腌,將那些被@Resource注解修飾的屬性注入到Bean
4、PersistenceAnnotationBeanPostProcessor執(zhí)行@ PersistenceContext等JPA注解的注入
*/
PropertyValues postProcessPropertyValues(PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException;
}
SmartInstantiationAwareBeanPostProcessor
public interface SmartInstantiationAwareBeanPostProcessor extends InstantiationAwareBeanPostProcessor {
/** 在調(diào)用{@link InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation}前預(yù)測要返回bean的類型*/
Class<?> predictBeanType(Class<?> beanClass, String beanName) throws BeansException;
// 確定一個(gè)實(shí)例化時(shí)要用的構(gòu)造器方法
Constructor<?>[] determineCandidateConstructors(Class<?> beanClass, String beanName) throws BeansException;
/**
該方法用于返回早期的Bean引用勾效,即半成品的Bean嘹悼,已經(jīng)實(shí)例化但是還沒有注入屬性
比如:CircularityA引用CircularityB,CircularityB引用CircularityC层宫,CircularityC引用CircularityA
(1)Spring容器創(chuàng)建單例“circularityA” Bean:首先依據(jù)無參構(gòu)造器創(chuàng)建“circularityA”Bean杨伙, 并暴露一個(gè)ObjectFactory,
這個(gè)ObjectFactory用于返回提前暴露的circularityA萌腿,然后將“circularityA”放到“當(dāng)前創(chuàng)建的Bean緩存池”中限匣。
然后進(jìn)行setter注入“circularityB”;
(2)Spring容器創(chuàng)建單例“circularityB” Bean:首先依據(jù)無參構(gòu)造器創(chuàng)建“circularityB" Bean毁菱,并暴露一個(gè)ObjectFactory米死,
于返回提前暴露的circularityB锌历。然后將 circularityB 放入“當(dāng)前創(chuàng)建的Bean緩存池”中,然后進(jìn)行setter注入 circularityC 峦筒;
(3)Spring容器創(chuàng)建單例“circularityC” Bean:首先依據(jù)無參構(gòu)造器創(chuàng)建“circularityC”Bean究西,并暴露一個(gè)ObjectFactory,
用于返回提前暴露的circularityC物喷。并將 circularityC 放入“當(dāng)前創(chuàng)建的Bean緩存池”中卤材, 然后進(jìn)行setter注入 circularityA ;
進(jìn)行注入“circularityA”時(shí)因?yàn)椴襟E(1)提前暴露了 circularityA 所以從之前的Cache里面拿BeanA脯丝,而不用反復(fù)創(chuàng)建商膊。
(4)最后在依賴注入“circularityB”和“circularityA”也是從catch里面拿提前暴露的bean。 完畢setter注入宠进。
該方法中晕拆,如果入?yún)ean是 circularityA 這個(gè)Bean,則在第一次創(chuàng)建circularityA時(shí)會(huì)返回一個(gè)半成品的Bean材蹬,已經(jīng)實(shí)例化但
是還沒有注入屬性实幕,我們稱這個(gè)半成品的bean為exposedObject,即早期暴露的Bean堤器。當(dāng)circularityC創(chuàng)建時(shí)昆庇,會(huì)先注入這個(gè)半成品
beanA,這樣就先完成了BeanC的創(chuàng)建闸溃,接著會(huì)完成BeanC的創(chuàng)建整吆,到最后BeanA時(shí),BeanC已經(jīng)完成了創(chuàng)建辉川,所以BeanA也就可以順利完
成表蝙。
此外,對(duì)于“prototype”作用域Bean乓旗。Spring容器無法完畢依賴注入府蛇,由于“prototype”作用域的Bean,Spring容器不進(jìn)行緩
存屿愚,因此無法提前暴露一個(gè)創(chuàng)建中的Bean汇跨。
還有就是,構(gòu)造函數(shù)循環(huán)依賴注入時(shí)妆距,也會(huì)拋異常穷遂。
*/
Object getEarlyBeanReference(Object bean, String beanName) throws BeansException;
}
MergedBeanDefinitionPostProcessor
public interface MergedBeanDefinitionPostProcessor extends BeanPostProcessor {
// BeanDefinition 被包裝為 BeanWrapper 后,會(huì)調(diào)用該方法娱据;典型的應(yīng)用是將自動(dòng)裝配@Autowired注解修飾的屬性保存到RootBeanDefinition#externallyManagedConfigMembers方便后續(xù)注入到Bean實(shí)例
void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName);
}
該處理在BeanFactory#doCreateBean的運(yùn)用場景(常規(guī)Bean創(chuàng)建的執(zhí)行步驟)如下:
//步驟一:實(shí)例化bean蚪黑,將 BeanDefinition 轉(zhuǎn)換為 BeanWrapper
// 這里是創(chuàng)建bean的地方,由createBeanInstance方法來完成,根據(jù)指定bean使用相應(yīng)的策略(如:工廠方法祠锣、構(gòu)造函數(shù)自動(dòng)注入、簡單初始化)創(chuàng)建實(shí)例
instanceWrapper = createBeanInstance(beanName, mbd, args);
//步驟二:MergedBeanDefinitionPostProcessor 的應(yīng)用
applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
//步驟三:依賴處理(會(huì)應(yīng)用SmartInstantiationAwareBeanPostProcessor處理器)
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences && isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
// 為避免后期循環(huán)依賴咽安,bean初始化完成前將創(chuàng)建實(shí)例的ObjectFactory加入緩存:
addSingletonFactory(beanName, new ObjectFactory<Object>() {
public Object getObject() throws BeansException {
// 對(duì)bean再一次依賴引用伴网,主要應(yīng)用SmartInstantiationAwareBeanPostProcessor
return getEarlyBeanReference(beanName, mbd, bean);
}
});
}
//步驟四:屬性填充,將所有屬性填充到bean實(shí)例中
populateBean(beanName, mbd, instanceWrapper);
DestructionAwareBeanPostProcessor
public interface DestructionAwareBeanPostProcessor extends BeanPostProcessor {
// 在bean實(shí)例銷毀前妆棒,將調(diào)用這個(gè)自定義銷毀的回調(diào)澡腾。
void postProcessBeforeDestruction(Object bean, String beanName) throws BeansException;
}
補(bǔ)充說明
InstantiationAwareBeanPostProcessor、DestructionAwareBeanPostProcessor這兩個(gè)分別是Bean在初始化和銷毀之前的回調(diào)方法
SmartInstantiationAwareBeanPostProcessor這個(gè)相當(dāng)于InstantiationAwareBeanPostProcessor的擴(kuò)展版本糕珊,增加了一個(gè)對(duì)Bean類型預(yù)測的回調(diào)动分,但這個(gè)主要是Spring框架內(nèi)部用的,用戶還是用InstantiationAwareBeanPostProcessor即可
MergedBeanDefinitionPostProcessor則是在合并處理Bean定義的時(shí)候的回調(diào)红选。這個(gè)東東按我的理解也基本是框架內(nèi)部使用的澜公,用戶不用管