Spring擴(kuò)展點(diǎn)總結(jié)

前面寫(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)用順序。


Spring流程
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末猛计,一起剝皮案震驚了整個(gè)濱河市唠摹,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌奉瘤,老刑警劉巖勾拉,帶你破解...
    沈念sama閱讀 206,968評(píng)論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異盗温,居然都是意外死亡藕赞,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,601評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門(mén)卖局,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)斧蜕,“玉大人,你說(shuō)我怎么就攤上這事砚偶∨” “怎么了洒闸?”我有些...
    開(kāi)封第一講書(shū)人閱讀 153,220評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)均芽。 經(jīng)常有香客問(wèn)我丘逸,道長(zhǎng),這世上最難降的妖魔是什么掀宋? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,416評(píng)論 1 279
  • 正文 為了忘掉前任深纲,我火速辦了婚禮,結(jié)果婚禮上劲妙,老公的妹妹穿的比我還像新娘湃鹊。我一直安慰自己,他們只是感情好镣奋,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,425評(píng)論 5 374
  • 文/花漫 我一把揭開(kāi)白布涛舍。 她就那樣靜靜地躺著,像睡著了一般唆途。 火紅的嫁衣襯著肌膚如雪富雅。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 49,144評(píng)論 1 285
  • 那天肛搬,我揣著相機(jī)與錄音没佑,去河邊找鬼。 笑死温赔,一個(gè)胖子當(dāng)著我的面吹牛蛤奢,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播陶贼,決...
    沈念sama閱讀 38,432評(píng)論 3 401
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼啤贩,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了拜秧?” 一聲冷哼從身側(cè)響起痹屹,我...
    開(kāi)封第一講書(shū)人閱讀 37,088評(píng)論 0 261
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎枉氮,沒(méi)想到半個(gè)月后志衍,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,586評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡聊替,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,028評(píng)論 2 325
  • 正文 我和宋清朗相戀三年楼肪,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片惹悄。...
    茶點(diǎn)故事閱讀 38,137評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡春叫,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情暂殖,我是刑警寧澤价匠,帶...
    沈念sama閱讀 33,783評(píng)論 4 324
  • 正文 年R本政府宣布,位于F島的核電站央星,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏惫东。R本人自食惡果不足惜莉给,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,343評(píng)論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望廉沮。 院中可真熱鬧颓遏,春花似錦、人聲如沸滞时。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,333評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)坪稽。三九已至曼玩,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間窒百,已是汗流浹背黍判。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,559評(píng)論 1 262
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留篙梢,地道東北人顷帖。 一個(gè)月前我還...
    沈念sama閱讀 45,595評(píng)論 2 355
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像渤滞,于是被迫代替她去往敵國(guó)和親贬墩。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,901評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容