前面寫(xiě)過(guò)一篇Spring擴(kuò)展的文章 Spring擴(kuò)展點(diǎn)1-NameSpaceHandler,本來(lái)想寫(xiě)系列文章恃慧,可是無(wú)意間看到一篇講Spring擴(kuò)展的文章,我感覺(jué)講得非常好需五,所以這里就偷個(gè)懶兆旬,轉(zhuǎn)載一下抄瓦。 本文轉(zhuǎn)載自 http://blog.gavinzh.com/2017/11/20/spring-develop-summary/
經(jīng)歷了一系列復(fù)雜的spring應(yīng)用后,你的項(xiàng)目可能已經(jīng)用上注解其爵,也用上了xxx.properties咖耘,你對(duì)這神奇的用法感到欣喜,但你不知道他是怎么被實(shí)現(xiàn)的,現(xiàn)在就讓我們來(lái)揭開(kāi)這些神秘的面紗维蒙。
BeanDefinition與BeanFactory擴(kuò)展
在Spring生成bean的過(guò)程這篇文章中掰吕,我們了解了spring在生成bean前會(huì)先生成bean的定義,然后注冊(cè)到BeanFactory中颅痊,再之后才能生成bean殖熟。那么對(duì)于從xml配置好的BeanDefinition,如果想要增加刪除修改該怎么辦呢斑响?
BeanDefinitionRegistryPostProcessor接口
BeanDefinitionRegistryPostProcessor接口繼承了BeanFactoryPostProcessor接口菱属,BeanFactoryPostProcessor接口隨后我們也會(huì)講到這個(gè)接口。
/**
* Extension to the standard {@link BeanFactoryPostProcessor} SPI, allowing for
* the registration of further bean definitions <i>before</i> regular
* BeanFactoryPostProcessor detection kicks in. In particular,
* BeanDefinitionRegistryPostProcessor may register further bean definitions
* which in turn define BeanFactoryPostProcessor instances.
*
* @author Juergen Hoeller
* @since 3.0.1
* @see org.springframework.context.annotation.ConfigurationClassPostProcessor
*/
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.
* @param registry the bean definition registry used by the application context
* @throws org.springframework.beans.BeansException in case of errors
*/
void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException;
}
這個(gè)接口擴(kuò)展了標(biāo)準(zhǔn)的BeanFactoryPostProcessor 接口恋捆,允許在普通的BeanFactoryPostProcessor接口實(shí)現(xiàn)類執(zhí)行之前注冊(cè)更多的BeanDefinition照皆。特別地是,BeanDefinitionRegistryPostProcessor可以注冊(cè)BeanFactoryPostProcessor的BeanDefinition沸停。
postProcessBeanDefinitionRegistry方法可以修改在BeanDefinitionRegistry接口實(shí)現(xiàn)類中注冊(cè)的任意BeanDefinition膜毁,也可以增加和刪除BeanDefinition。原因是這個(gè)方法執(zhí)行前所有常規(guī)的BeanDefinition已經(jīng)被加載到BeanDefinitionRegistry接口實(shí)現(xiàn)類中愤钾,但還沒(méi)有bean被實(shí)例化瘟滨。
接口應(yīng)用
我們僅僅需要寫(xiě)一個(gè)類實(shí)現(xiàn)接口,然后將這個(gè)類配置到spring的xml配置中能颁。以下是我寫(xiě)的一個(gè)簡(jiǎn)單的實(shí)現(xiàn)類:
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
public class DefaultBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor {
private Logger logger = LoggerFactory.getLogger(this.getClass());
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
logger.info("BeanDefinitionRegistryPostProcessor的postProcessBeanDefinitionRegistry方法,在這里可以增加修改刪除bean的定義");
}
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
logger.info("BeanDefinitionRegistryPostProcessor的postProcessBeanFactory方法,在這里可以對(duì)beanFactory做一些操作");
}
}
實(shí)際上杂瘸,Mybatis中org.mybatis.spring.mapper.MapperScannerConfigurer就實(shí)現(xiàn)了該方法,在只有接口沒(méi)有實(shí)現(xiàn)類的情況下找到接口方法與sql之間的聯(lián)系從而生成BeanDefinition并注冊(cè)伙菊。而Spring的org.springframework.context.annotation.ConfigurationClassPostProcessor也是用來(lái)將注解@Configuration中的相關(guān)生成bean的方法所對(duì)應(yīng)的BeanDefinition進(jìn)行注冊(cè)败玉。
1.2.BeanFactoryPostProcessor接口
BeanFactory生成后,如果想對(duì)BeanFactory進(jìn)行一些處理镜硕,該怎么辦呢运翼?BeanFactoryPostProcessor接口就是用來(lái)處理BeanFactory的。
/**
* Allows for custom modification of an application context's bean definitions,
* adapting the bean property values of the context's underlying bean factory.
*
* <p>Application contexts can auto-detect BeanFactoryPostProcessor beans in
* their bean definitions and apply them before any other beans get created.
*
* <p>Useful for custom config files targeted at system administrators that
* override bean properties configured in the application context.
*
* <p>See PropertyResourceConfigurer and its concrete implementations
* for out-of-the-box solutions that address such configuration needs.
*
* <p>A BeanFactoryPostProcessor may interact with and modify bean
* definitions, but never bean instances. Doing so may cause premature bean
* instantiation, violating the container and causing unintended side-effects.
* If bean instance interaction is required, consider implementing
* {@link BeanPostProcessor} instead.
*
* @author Juergen Hoeller
* @since 06.07.2003
* @see BeanPostProcessor
* @see PropertyResourceConfigurer
*/
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;
}
這個(gè)接口允許自定義修改應(yīng)用程序上下文的BeanDefinition兴枯,調(diào)整上下文的BeanFactory的bean屬性值血淌。應(yīng)用程序上下文可以在BeanFactory的BeanDefinition中自動(dòng)檢測(cè)BeanFactoryPostProcessor bean,并在創(chuàng)建任何其他bean之前應(yīng)用它們财剖。對(duì)于定位于系統(tǒng)管理員的自定義配置文件非常有用悠夯,它們將覆蓋應(yīng)用程序上下文中配置的bean屬性。請(qǐng)參閱PropertyResourceConfigurer及其具體實(shí)現(xiàn)躺坟,了解解決此類配置需求的開(kāi)箱即用解決方案沦补。BeanFactoryPostProcessor可能與bean定義交互并修改,但永遠(yuǎn)不應(yīng)該將bean實(shí)例化咪橙。 這樣做可能會(huì)導(dǎo)致過(guò)早的bean實(shí)例化策彤,違反容器執(zhí)行順序并導(dǎo)致意想不到的副作用栓袖。如果需要bean實(shí)例交互,請(qǐng)考慮實(shí)現(xiàn)BeanPostProcessor接口店诗。
postProcessBeanFactory方法在BeanFactory初始化后裹刮,所有的bean定義都被加載,但是沒(méi)有bean會(huì)被實(shí)例化時(shí)庞瘸,允許重寫(xiě)或添加屬性捧弃。
接口應(yīng)用
DefaultBeanDefinitionRegistryPostProcessor接口一樣,實(shí)現(xiàn)并配置到spring的xml配置中即可擦囊。
最常用的一個(gè)應(yīng)用就是org.springframework.beans.factory.config.PropertyPlaceholderConfigurer违霞,BeanDefinition生成后,可能某些參數(shù)是${key}瞬场,這個(gè)實(shí)現(xiàn)類就是把前邊這種參數(shù)轉(zhuǎn)換成xxx.properties中key所對(duì)應(yīng)的值买鸽。
Bean實(shí)例化中的擴(kuò)展
前一小節(jié)關(guān)注的是BeanDefinition和BeanFactory,那么在bean的實(shí)例化過(guò)程中會(huì)調(diào)用一些特定的接口實(shí)現(xiàn)類贯被,這些接口都有哪些眼五?
InstantiationAwareBeanPostProcessor接口
/**
* Subinterface of {@link BeanPostProcessor} that adds a before-instantiation callback,
* and a callback after instantiation but before explicit properties are set or
* autowiring occurs.
*
* <p>Typically used to suppress default instantiation for specific target beans,
* for example to create proxies with special TargetSources (pooling targets,
* lazily initializing targets, etc), or to implement additional injection strategies
* such as field injection.
*
* <p><b>NOTE:</b> This interface is a special purpose interface, mainly for
* internal use within the framework. It is recommended to implement the plain
* {@link BeanPostProcessor} interface as far as possible, or to derive from
* {@link InstantiationAwareBeanPostProcessorAdapter} in order to be shielded
* from extensions to this interface.
*
* @author Juergen Hoeller
* @author Rod Johnson
* @since 1.2
* @see org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#setCustomTargetSourceCreators
* @see org.springframework.aop.framework.autoproxy.target.LazyInitTargetSourceCreator
*/
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
* {@link #postProcessAfterInitialization} callback from the configured
* {@link BeanPostProcessor BeanPostProcessors}.
* <p>This callback will only be applied to bean definitions with a bean class.
* In particular, it will not be applied to beans with a "factory-method".
* <p>Post-processors may implement the extended
* {@link SmartInstantiationAwareBeanPostProcessor} interface in order
* to predict the type of the bean object that they are going to return here.
* @param beanClass the class of the bean to be instantiated
* @param beanName the name of the bean
* @return the bean object to expose instead of a default instance of the target bean,
* or {@code null} to proceed with default instantiation
* @throws org.springframework.beans.BeansException in case of errors
* @see org.springframework.beans.factory.support.AbstractBeanDefinition#hasBeanClass
* @see org.springframework.beans.factory.support.AbstractBeanDefinition#getFactoryMethodName
*/
Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException;
/**
* 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.
* <p>This is the ideal callback for performing custom field injection on the given bean
* instance, right before Spring's autowiring kicks in.
* @param bean the bean instance created, with properties not having been set yet
* @param beanName the name of the bean
* @return {@code true} if properties should be set on the bean; {@code false}
* if property population should be skipped. Normal implementations should return {@code true}.
* Returning {@code false} will also prevent any subsequent InstantiationAwareBeanPostProcessor
* instances being invoked on this bean instance.
* @throws org.springframework.beans.BeansException in case of errors
*/
boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException;
/**
* 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.
* @param pvs the property values that the factory is about to apply (never {@code null})
* @param pds the relevant property descriptors for the target bean (with ignored
* dependency types - which the factory handles specifically - already filtered out)
* @param bean the bean instance created, but whose properties have not yet been set
* @param beanName the name of the bean
* @return the actual property values to apply to the given bean
* (can be the passed-in PropertyValues instance), or {@code null}
* to skip property population
* @throws org.springframework.beans.BeansException in case of errors
* @see org.springframework.beans.MutablePropertyValues
*/
PropertyValues postProcessPropertyValues(
PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException;
}
這個(gè)接口是BeanPostProcessor的子接口,用于在實(shí)例化之后彤灶,但在設(shè)置顯式屬性或自動(dòng)裝配之前看幼,設(shè)置實(shí)例化之前的回調(diào)函數(shù)。通常用于抑制特定目標(biāo)bean的默認(rèn)實(shí)例化幌陕,例如诵姜,創(chuàng)建具有特殊TargetSources(池化目標(biāo),延遲初始化目標(biāo)等)的代理搏熄,或者實(shí)現(xiàn)其他注入策略棚唆,例如字段注入。注意:這個(gè)接口是一個(gè)專用接口心例,主要用于框架內(nèi)的內(nèi)部使用宵凌。 建議盡可能實(shí)現(xiàn)簡(jiǎn)單的BeanPostProcessor接口,或者從InstantiationAwareBeanPostProcessorAdapter派生契邀,以便屏蔽此接口的擴(kuò)展摆寄。
postProcessBeforeInstantiation方法失暴,在目標(biāo)bean實(shí)例化之前創(chuàng)建bean坯门,如果在這里創(chuàng)建了bean,則不會(huì)走默認(rèn)的實(shí)例化過(guò)程逗扒,通常用來(lái)創(chuàng)建代理古戴。注意工廠方法生成的bean不會(huì)走這個(gè)方法。
postProcessAfterInstantiation方法矩肩,在目標(biāo)bean實(shí)例化后现恼,但是沒(méi)有進(jìn)行屬性填充前執(zhí)行的方法。
postProcessPropertyValues方法,在將給定屬性值設(shè)置到到給定的bean后叉袍,對(duì)其進(jìn)行后處理始锚。 允許檢查所有的依賴關(guān)系是否被滿足,例如基于bean屬性設(shè)置器上的“Required”注解喳逛。還允許替換要應(yīng)用的屬性值瞧捌,通常通過(guò)創(chuàng)建基于原始PropertyValues的新MutablePropertyValues實(shí)例,添加或刪除特定值润文。
接口應(yīng)用
這個(gè)接口spring不建議用戶直接實(shí)現(xiàn)姐呐,如果必須在這些擴(kuò)展點(diǎn)應(yīng)用自己的回調(diào)函數(shù),spring建議繼承InstantiationAwareBeanPostProcessorAdapter典蝌,重寫(xiě)相應(yīng)的方法即可曙砂。
org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator,基于beanName創(chuàng)建代理骏掀,就是應(yīng)用了這個(gè)接口鸠澈,在生成bean前生成代理bean,從而替代默認(rèn)的實(shí)例化砖织。
BeanPostProcessor接口
/**
* Factory hook that allows for custom modification of new bean instances,
* e.g. checking for marker interfaces or wrapping them with proxies.
*
* <p>ApplicationContexts can autodetect BeanPostProcessor beans in their
* bean definitions and apply them to any beans subsequently created.
* Plain bean factories allow for programmatic registration of post-processors,
* applying to all beans created through this factory.
*
* <p>Typically, post-processors that populate beans via marker interfaces
* or the like will implement {@link #postProcessBeforeInitialization},
* while post-processors that wrap beans with proxies will normally
* implement {@link #postProcessAfterInitialization}.
*
* @author Juergen Hoeller
* @since 10.10.2003
* @see InstantiationAwareBeanPostProcessor
* @see DestructionAwareBeanPostProcessor
* @see ConfigurableBeanFactory#addBeanPostProcessor
* @see BeanFactoryPostProcessor
*/
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.
* @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
*/
Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;
/**
* 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.
* @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
*/
Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;
}
這個(gè)接口款侵,允許自定義修改新的bean實(shí)例,例如檢查標(biāo)記接口或用代理包裝侧纯,注意新锈,如果有相互依賴的bean,這里可能無(wú)法使用代理眶熬。
postProcessBeforeInitialization方法妹笆,在任何bean初始化回調(diào)(如InitializingBean的afterPropertiesSet或自定義init方法)之前,將此BeanPostProcessor應(yīng)用于給定的新的bean實(shí)例娜氏。 這個(gè)bean已經(jīng)被填充了屬性值拳缠。 返回的bean實(shí)例可能是原始的包裝器。
postProcessAfterInitialization方法贸弥,在Bean初始化回調(diào)(如InitializingBean的afterPropertiesSet或自定義init方法)之后窟坐,將此BeanPostProcessor應(yīng)用于給定的新bean實(shí)例。 這個(gè)bean已經(jīng)被填充了屬性值绵疲。 返回的bean實(shí)例可能是原始的包裝器哲鸳。這個(gè)方法也會(huì)在InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation方法生成對(duì)象后再次不讓他生成對(duì)象(具體可以參考Spring生成bean的過(guò)程)。
接口應(yīng)用
org.springframework.context.support.ApplicationContextAwareProcessor就是在bean初始化回調(diào)之前盔憨,注入應(yīng)用上下文的徙菠。
其他擴(kuò)展點(diǎn)
InitializingBean接口
在執(zhí)行完BeanPostProcessor的postProcessBeforeInitialization方法后,如果這個(gè)bean實(shí)現(xiàn)了InitializingBean接口郁岩,則會(huì)去調(diào)用afterPropertiesSet方法婿奔。
各種Aware
在在執(zhí)行完BeanPostProcessor的postProcessBeforeInitialization方法前缺狠,如果bean實(shí)現(xiàn)了BeanNameAware或BeanClassLoaderAware或BeanFactoryAware,則會(huì)調(diào)用接口相關(guān)的方法萍摊,入?yún)⒕褪沁@個(gè)bean關(guān)心的值挤茄。
ApplicationContextAwareProcessor,作用是在一個(gè)bean初始化之前冰木,如果這個(gè)bean有Aware接口驮樊,實(shí)現(xiàn)了EnvironmentAware,EmbeddedValueResolverAware,ResourceLoaderAware片酝,ApplicationEventPublisherAware囚衔,MessageSourceAware,ApplicationContextAware相關(guān)接口雕沿,就通過(guò)這些aware的相關(guān)接口將上下文設(shè)置進(jìn)去练湿,上述接口除了EmbeddedValueResolverAware接口ClassPathXmlApplicationContext沒(méi)有實(shí)現(xiàn),其他都實(shí)現(xiàn)了审轮,也就是說(shuō)肥哎,調(diào)用這些接口的方法入?yún)⒍际荂lassPathXmlApplicationContext就可以了。EmbeddedValueResolverAware的入?yún)⑹荅mbeddedValueResolver疾渣,它的構(gòu)造函數(shù)入?yún)⑹巧舷挛闹械腷eanFactory篡诽。
BeanDefinition入口擴(kuò)展
在定義bean時(shí),可以指定構(gòu)造函數(shù)榴捡,設(shè)置屬性杈女,還可以設(shè)置init-method和destroy-method。構(gòu)造函數(shù)不用說(shuō)吊圾,設(shè)置屬性是在InstantiationAwareBeanPostProcessor#PostProcessPropertyValues方法后執(zhí)行的达椰,init-method是在InitializingBean的afterPropertiesSet方法后執(zhí)行的,而destroy-method是在容器關(guān)閉是被調(diào)用的项乒。
擴(kuò)展點(diǎn)在spring中的注入
前三小節(jié)我們了解了很多擴(kuò)展點(diǎn)啰劲,那這些擴(kuò)展點(diǎn)中的接口是怎么在spring中生效的呢,換句話說(shuō)在什么時(shí)候被調(diào)用或被添加到BeanFactory中等待調(diào)用呢檀何?
容器級(jí)別
我們得從上下文的抽象類AbstractApplicationContext#refresh方法講起
@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// Prepare this context for refreshing.
// 設(shè)置上下文啟動(dòng)時(shí)間和活躍標(biāo)記蝇裤,同時(shí)加載屬性資源。
prepareRefresh();
// Tell the subclass to refresh the internal bean factory.
// 停掉之前啟動(dòng)的beanFactory如果有的話频鉴,同時(shí)新生成一個(gè)beanFactory栓辜,加載配置中的BeanDefinition。
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// Prepare the bean factory for use in this context.
// 給beanFactory設(shè)置類加載器砚殿,添加后置處理器`ApplicationContextAwareProcessor`等等啃憎。
prepareBeanFactory(beanFactory);
try {
// 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();
}
catch (BeansException ex) {
if (logger.isWarnEnabled()) {
logger.warn("Exception encountered during context initialization - " +
"cancelling refresh attempt: " + ex);
}
// Destroy already created singletons to avoid dangling resources.
destroyBeans();
// Reset 'active' flag.
cancelRefresh(ex);
// Propagate exception to caller.
throw ex;
}
finally {
// Reset common introspection caches in Spring's core, since we
// might not ever need metadata for singleton beans anymore...
resetCommonCaches();
}
}
}
nvokeBeanFactoryPostProcessors(beanFactory)方法就是第一小節(jié)提到的BeanDefinitionRegistryPostProcessor和BeanFactoryPostProcessor的調(diào)用芝囤。
invokeBeanFactoryPostProcessors方法的調(diào)用邏輯:
如果beanFactory是BeanDefinitionRegistry的實(shí)現(xiàn)類
拿到入?yún)⑺械腂eanFactoryPostProcessor接口實(shí)現(xiàn)類似炎,挑選出實(shí)現(xiàn)BeanDefinitionRegistryPostProcessor接口的實(shí)現(xiàn)類先執(zhí)行postProcessBeanDefinitionRegistry方法辛萍。
接下來(lái)調(diào)用beanFactory中實(shí)現(xiàn)BeanDefinitionRegistryPostProcessor接口的實(shí)現(xiàn)類中實(shí)現(xiàn)PriorityOrdered接口的實(shí)現(xiàn)類,調(diào)用這些實(shí)現(xiàn)類前先根據(jù)PriorityOrdered的getOrder方法進(jìn)行排序羡藐,然后再按順序調(diào)用postProcessBeanDefinitionRegistry方法贩毕。
接下來(lái)再調(diào)用beanFactory中實(shí)現(xiàn)BeanDefinitionRegistryPostProcessor接口的實(shí)現(xiàn)類中實(shí)現(xiàn)了Ordered接口的類,也是按順序調(diào)用postProcessBeanDefinitionRegistry方法仆嗦。
最后調(diào)用beanFactory中其他的實(shí)現(xiàn)BeanDefinitionRegistryPostProcessor接口的實(shí)現(xiàn)類的postProcessBeanDefinitionRegistry方法辉阶。
最后的最后,先調(diào)用入?yún)⒅兴袑?shí)現(xiàn)BeanDefinitionRegistryPostProcessor接口的實(shí)現(xiàn)類的postProcessBeanFactory方法瘩扼,再調(diào)用入?yún)⒅袑?shí)現(xiàn)了BeanFactoryPostProcessor接口的實(shí)現(xiàn)類的postProcessBeanFactory方法谆甜。
如果不是則只把入?yún)⒅械腂eanFactoryPostProcessor實(shí)現(xiàn)類全部調(diào)用一遍。
上邊都做完了集绰,接著從beanFactory中獲取實(shí)現(xiàn)了BeanFactoryPostProcessor接口的bean(沒(méi)有被執(zhí)行過(guò))规辱,也是分為三類,PriorityOrdered組優(yōu)先調(diào)用栽燕,Ordered其次罕袋,其他墊底。
最終清除beanFactory的metaData緩存(主要是清除類與beanname的映射緩存
registerBeanPostProcessors(beanFactory)方法就是第二小節(jié)中BeanPostProcessor接口實(shí)現(xiàn)類的注冊(cè)碍岔。
registerBeanPostProcessors方法的調(diào)用邏輯:
先添加BeanPostProcessorChecker浴讯。
然后把beanFactory中實(shí)現(xiàn)BeanPostProcessor接口的實(shí)現(xiàn)類分成四個(gè)部分分別添加到beanFactory。
PriorityOrdered部分蔼啦,實(shí)現(xiàn)了PriorityOrdered接口且并不屬于MergedBeanDefinitionPostProcessor的
Ordered部分榆纽,實(shí)現(xiàn)了Ordered接口且并不屬于MergedBeanDefinitionPostProcessor的
其他的不屬于MergedBeanDefinitionPostProcessor的
屬于MergedBeanDefinitionPostProcessor的
其中PriorityOrdered和Ordered部分先排序,然后按上邊的順序分別加入到beanFactory的beanPostProcessors屬性中
bean級(jí)別
其余的bean上的接口屬性之類的捏肢,都是在bean的生成中逐個(gè)調(diào)用的掠河。
小結(jié)
下面由一張圖來(lái)總結(jié)一下擴(kuò)展點(diǎn)之間的調(diào)用順序。