Spring筆記(6) - Spring的BeanFactoryPostProcessor探究

一.背景

  在說BeanFactoryPostProcessor以前,先來講下BeanPostProcessor,在前文Spring筆記(2) - 生命週期/屬性賦值/自動裝配及部分源碼解析中講解了BeanPostProcessor是一個bean後置處理器(bean建立對象初始化先後進行攔截工做)。html

  BeanPostProcessor的運行流程以下:java

    1)Spring IOC容器實例化Bean;spring

    2)調用BeanPostProcessor的postProcessBeforeInitialization方法;緩存

    3)調用bean實例的初始化方法;springboot

    4)調用BeanPostProcessor的postProcessAfterInitialization方法; app

  實現BeanPostProcessor接口能夠在Bean(實例化以後)初始化的先後作一些自定義的操做,可是拿到的參數只有BeanDefinition實例和BeanDefinition的名稱,也就是沒法修改BeanDefinition元數據,這裏說的Bean的初始化是:less

    1)bean實現了InitializingBean接口,對應的方法爲afterPropertiesSet ide

    2)在bean定義的時候,經過init-method設置的方法函數

  Spring中Bean的實例化過程圖示:  post


  那麼BeanFactoryPostProcessor顧名思義就是bean工廠的後置處理器,說通俗一些就是能夠管理咱們的bean工廠內全部的BeanDefinition(未實例化)數據,能夠爲所欲爲的修改屬性。            

  Spring容器初始化時,從資源中讀取到bean的相關定義後,保存在beanFactory的成員變量中(參考DefaultListableBeanFactory類的成員變量beanDefinitionMap),在實例化bean的操做就是依據這些bean的定義來作的,而在實例化以前,Spring容許咱們經過自定義擴展來改變bean的定義,定義一旦變了,後面的實例也就變了,而beanFactory後置處理器,即BeanFactoryPostProcessor就是用來改變bean定義的;若是業務須要,能夠配置多個BeanFactoryPostProcessor的實現類,經過」order」控制執行次序(要實現Ordered接口)。

  註冊一個BeanFactoryPostProcessor實例須要定義一個Java類來實現BeanFactoryPostProcessor接口,並重寫該接口的postProcessorBeanFactory方法。經過beanFactory能夠獲取bean的定義信息,並能夠修改bean的定義信息。(這點是和BeanPostProcessor最大區別)

  因此經過上面的介紹能夠總結出有兩種方式能夠對bean作控制(例如修改某個成員變量):

    1. 只改變實例化的對象(BeanPostProcessor接口);

    2. 改變bean的定義(BeanFactoryPostProcessor接口) ,能夠想象成修改了class文件,這樣實例化出來的每一個對象都變了;  

  PS:BeanFactoryPostProcessor回調會先於BeanPostProcessor  

  下面是BeanFactoryPostProcessor的源碼:

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
     */
     //在ioc容器的bean Factory標準初始化以後能夠對它們進行修改。全部的bean定義被加載了,但尚未被實例化。
     //容許進行重載或添加屬性即便在eager-initializing beans
    void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;

}

  BeanFactoryPostProcessor此接口只提供了一個方法,方法參數爲ConfigurableListableBeanFactory,下面是該類的源碼: 

public interface ConfigurableListableBeanFactory
        extends ListableBeanFactory, AutowireCapableBeanFactory, ConfigurableBeanFactory {

    void ignoreDependencyType(Class<?> type);

    void ignoreDependencyInterface(Class<?> ifc);

    void registerResolvableDependency(Class<?> dependencyType, @Nullable Object autowiredValue);

    boolean isAutowireCandidate(String beanName, DependencyDescriptor descriptor)
            throws NoSuchBeanDefinitionException;

    BeanDefinition getBeanDefinition(String beanName) throws NoSuchBeanDefinitionException;

    Iterator<String> getBeanNamesIterator();

    void clearMetadataCache();

    void freezeConfiguration();

    boolean isConfigurationFrozen();

    void preInstantiateSingletons() throws BeansException;

}

  其中有個方法名爲getBeanDefinition的方法,咱們能夠根據此方法,找到咱們定義bean的BeanDefinition對象。而後咱們能夠對定義的屬性進行修改,如下是BeanDefinition中的方法:

public interface BeanDefinition extends AttributeAccessor, BeanMetadataElement {

    /**
     * Scope identifier for the standard singleton scope: "singleton".
     * <p>Note that extended bean factories might support further scopes.
     * @see #setScope
     */
    String SCOPE_SINGLETON = ConfigurableBeanFactory.SCOPE_SINGLETON;

    /**
     * Scope identifier for the standard prototype scope: "prototype".
     * <p>Note that extended bean factories might support further scopes.
     * @see #setScope
     */
    String SCOPE_PROTOTYPE = ConfigurableBeanFactory.SCOPE_PROTOTYPE;


    /**
     * Role hint indicating that a {@code BeanDefinition} is a major part
     * of the application. Typically corresponds to a user-defined bean.
     */
    int ROLE_APPLICATION = 0;

    /**
     * Role hint indicating that a {@code BeanDefinition} is a supporting
     * part of some larger configuration, typically an outer
     * {@link org.springframework.beans.factory.parsing.ComponentDefinition}.
     * {@code SUPPORT} beans are considered important enough to be aware
     * of when looking more closely at a particular
     * {@link org.springframework.beans.factory.parsing.ComponentDefinition},
     * but not when looking at the overall configuration of an application.
     */
    int ROLE_SUPPORT = 1;

    /**
     * Role hint indicating that a {@code BeanDefinition} is providing an
     * entirely background role and has no relevance to the end-user. This hint is
     * used when registering beans that are completely part of the internal workings
     * of a {@link org.springframework.beans.factory.parsing.ComponentDefinition}.
     */
    int ROLE_INFRASTRUCTURE = 2;


    // Modifiable attributes

    /**
     * Set the name of the parent definition of this bean definition, if any.
     */
    void setParentName(@Nullable String parentName);

    /**
     * Return the name of the parent definition of this bean definition, if any.
     */
    @Nullable
    String getParentName();

    /**
     * Specify the bean class name of this bean definition.
     * <p>The class name can be modified during bean factory post-processing,
     * typically replacing the original class name with a parsed variant of it.
     * @see #setParentName
     * @see #setFactoryBeanName
     * @see #setFactoryMethodName
     */
    void setBeanClassName(@Nullable String beanClassName);

    /**
     * Return the current bean class name of this bean definition.
     * <p>Note that this does not have to be the actual class name used at runtime, in
     * case of a child definition overriding/inheriting the class name from its parent.
     * Also, this may just be the class that a factory method is called on, or it may
     * even be empty in case of a factory bean reference that a method is called on.
     * Hence, do <i>not</i> consider this to be the definitive bean type at runtime but
     * rather only use it for parsing purposes at the individual bean definition level.
     * @see #getParentName()
     * @see #getFactoryBeanName()
     * @see #getFactoryMethodName()
     */
    @Nullable
    String getBeanClassName();

    /**
     * Override the target scope of this bean, specifying a new scope name.
     * @see #SCOPE_SINGLETON
     * @see #SCOPE_PROTOTYPE
     */
    void setScope(@Nullable String scope);

    /**
     * Return the name of the current target scope for this bean,
     * or {@code null} if not known yet.
     */
    @Nullable
    String getScope();

    /**
     * Set whether this bean should be lazily initialized.
     * <p>If {@code false}, the bean will get instantiated on startup by bean
     * factories that perform eager initialization of singletons.
     */
    void setLazyInit(boolean lazyInit);

    /**
     * Return whether this bean should be lazily initialized, i.e. not
     * eagerly instantiated on startup. Only applicable to a singleton bean.
     */
    boolean isLazyInit();

    /**
     * Set the names of the beans that this bean depends on being initialized.
     * The bean factory will guarantee that these beans get initialized first.
     */
    void setDependsOn(@Nullable String... dependsOn);

    /**
     * Return the bean names that this bean depends on.
     */
    @Nullable
    String[] getDependsOn();

    /**
     * Set whether this bean is a candidate for getting autowired into some other bean.
     * <p>Note that this flag is designed to only affect type-based autowiring.
     * It does not affect explicit references by name, which will get resolved even
     * if the specified bean is not marked as an autowire candidate. As a consequence,
     * autowiring by name will nevertheless inject a bean if the name matches.
     */
    void setAutowireCandidate(boolean autowireCandidate);

    /**
     * Return whether this bean is a candidate for getting autowired into some other bean.
     */
    boolean isAutowireCandidate();

    /**
     * Set whether this bean is a primary autowire candidate.
     * <p>If this value is {@code true} for exactly one bean among multiple
     * matching candidates, it will serve as a tie-breaker.
     */
    void setPrimary(boolean primary);

    /**
     * Return whether this bean is a primary autowire candidate.
     */
    boolean isPrimary();

    /**
     * Specify the factory bean to use, if any.
     * This the name of the bean to call the specified factory method on.
     * @see #setFactoryMethodName
     */
    void setFactoryBeanName(@Nullable String factoryBeanName);

    /**
     * Return the factory bean name, if any.
     */
    @Nullable
    String getFactoryBeanName();

    /**
     * Specify a factory method, if any. This method will be invoked with
     * constructor arguments, or with no arguments if none are specified.
     * The method will be invoked on the specified factory bean, if any,
     * or otherwise as a static method on the local bean class.
     * @see #setFactoryBeanName
     * @see #setBeanClassName
     */
    void setFactoryMethodName(@Nullable String factoryMethodName);

    /**
     * Return a factory method, if any.
     */
    @Nullable
    String getFactoryMethodName();

    /**
     * Return the constructor argument values for this bean.
     * <p>The returned instance can be modified during bean factory post-processing.
     * @return the ConstructorArgumentValues object (never {@code null})
     */
    ConstructorArgumentValues getConstructorArgumentValues();

    /**
     * Return if there are constructor argument values defined for this bean.
     * @since 5.0.2
     */
    default boolean hasConstructorArgumentValues() {
        return !getConstructorArgumentValues().isEmpty();
    }

    /**
     * Return the property values to be applied to a new instance of the bean.
     * <p>The returned instance can be modified during bean factory post-processing.
     * @return the MutablePropertyValues object (never {@code null})
     */
    MutablePropertyValues getPropertyValues();

    /**
     * Return if there are property values values defined for this bean.
     * @since 5.0.2
     */
    default boolean hasPropertyValues() {
        return !getPropertyValues().isEmpty();
    }

    /**
     * Set the name of the initializer method.
     * @since 5.1
     */
    void setInitMethodName(@Nullable String initMethodName);

    /**
     * Return the name of the initializer method.
     * @since 5.1
     */
    @Nullable
    String getInitMethodName();

    /**
     * Set the name of the destroy method.
     * @since 5.1
     */
    void setDestroyMethodName(@Nullable String destroyMethodName);

    /**
     * Return the name of the destroy method.
     * @since 5.1
     */
    @Nullable
    String getDestroyMethodName();

    /**
     * Set the role hint for this {@code BeanDefinition}. The role hint
     * provides the frameworks as well as tools with an indication of
     * the role and importance of a particular {@code BeanDefinition}.
     * @since 5.1
     * @see #ROLE_APPLICATION
     * @see #ROLE_SUPPORT
     * @see #ROLE_INFRASTRUCTURE
     */
    void setRole(int role);

    /**
     * Get the role hint for this {@code BeanDefinition}. The role hint
     * provides the frameworks as well as tools with an indication of
     * the role and importance of a particular {@code BeanDefinition}.
     * @see #ROLE_APPLICATION
     * @see #ROLE_SUPPORT
     * @see #ROLE_INFRASTRUCTURE
     */
    int getRole();

    /**
     * Set a human-readable description of this bean definition.
     * @since 5.1
     */
    void setDescription(@Nullable String description);

    /**
     * Return a human-readable description of this bean definition.
     */
    @Nullable
    String getDescription();


    // Read-only attributes

    /**
     * Return a resolvable type for this bean definition,
     * based on the bean class or other specific metadata.
     * <p>This is typically fully resolved on a runtime-merged bean definition
     * but not necessarily on a configuration-time definition instance.
     * @return the resolvable type (potentially {@link ResolvableType#NONE})
     * @since 5.2
     * @see ConfigurableBeanFactory#getMergedBeanDefinition
     */
    ResolvableType getResolvableType();

    /**
     * Return whether this a <b>Singleton</b>, with a single, shared instance
     * returned on all calls.
     * @see #SCOPE_SINGLETON
     */
    boolean isSingleton();

    /**
     * Return whether this a <b>Prototype</b>, with an independent instance
     * returned for each call.
     * @since 3.0
     * @see #SCOPE_PROTOTYPE
     */
    boolean isPrototype();

    /**
     * Return whether this bean is "abstract", that is, not meant to be instantiated.
     */
    boolean isAbstract();

    /**
     * Return a description of the resource that this bean definition
     * came from (for the purpose of showing context in case of errors).
     */
    @Nullable
    String getResourceDescription();

    /**
     * Return the originating BeanDefinition, or {@code null} if none.
     * Allows for retrieving the decorated bean definition, if any.
     * <p>Note that this method returns the immediate originator. Iterate through the
     * originator chain to find the original BeanDefinition as defined by the user.
     */
    @Nullable
    BeanDefinition getOriginatingBeanDefinition();

}
View Code

  咱們能夠在上面代碼中發現裏面的方法名字相似bean標籤的屬性,setBeanClassName對應bean標籤中的class屬性,因此當咱們拿到BeanDefinition對象時,咱們能夠手動修改bean標籤中所定義的屬性值。

  具體這個BeanDefinition是個什麼對象,當咱們在xml中定義了bean標籤時,Spring會把這些bean標籤解析成一個javabean,這個BeanDefinition就是bean標籤對應的javabean。

  因此當咱們調用BeanFactoryPostProcess方法時,這時候bean尚未實例化,此時bean剛被解析成BeanDefinition對象。

  Spring容器初始化bean大體過程 :

    1)定義bean標籤

    2)將bean標籤解析成BeanDefinition

    3)調用構造方法實例化(IOC)

    4)屬性值得依賴注入(DI)

  因此能夠看出BeanFactoryPostProcess方法的執行是發生在第二步以後,第三步以前。

  綜上所述BeanPostProcessor和BeanFactoryPostProcess都是爲Spring提供的後處理bean的接口,只是二者執行的時機不同。BeanPostProcessor爲實例化以後,BeanFactoryPostProcess是實例化以前。功能上,BeanFactoryPostProcess對bean的處理功能更增強大。

二.案例

   1.配置類:進行包掃描將類加載到容器中

@ComponentScan("com.hrh.ext")
@Configuration
public class ExtConfig {
    @Bean
    public Person person() {
        return new Person("張三", "男");
    }
}

  2.實體類:

public class Person implements InitializingBean, DisposableBean, BeanNameAware, BeanFactoryAware {
private String name;
private String sex;

    public Person() {
        System.out.println("Person無參構造器");

    }

    public Person(String name, String sex) {
        System.out.println("Person有參構造器:[name=" + name + ",sex=" + sex + "]");
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        System.out.println("[Person]調用了BeanFactoryAware的setBeanFactory方法了:" + beanFactory);
    }

    @Override
    public void setBeanName(String name) {
        System.out.println("[Person]調用了BeanNameAware的setBeanName方法了:" + name);
    }

    @Override
    public void destroy() throws Exception {
        System.out.println("[Person]調用了DisposableBean的destroy方法了");
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("[Person]調用了Initailization的afterPropertiesSet方法了");
    }

    @Override
    public String toString() {
        return "Person [name=" + name + ", sex=" + sex
                + "]";
    }
}

   3.自定義BeanFactoryPostProcessor類:

@Component
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        System.out.println("[MyBeanFactoryPostProcessor]調用了postProcessBeanFactory");
        int count = beanFactory.getBeanDefinitionCount();
        System.out.println("[MyBeanFactoryPostProcessor]當前beanFactory共有" + count + "個bean");
        String[] beanDefinitionNames = beanFactory.getBeanDefinitionNames();
        System.out.println("[MyBeanFactoryPostProcessor]當前beanFactory有下面組件" + Arrays.asList(beanDefinitionNames));
        //獲取容器中全部的beanDefinition
        for (String beanName : beanDefinitionNames) {
            if ("person".equals(beanName)) {
                //獲取PersonDefinition對象
                BeanDefinition beanDefinition = beanFactory.getBeanDefinition(beanName);
                MutablePropertyValues propertyValues = beanDefinition.getPropertyValues();
                System.out.println(propertyValues.toString());
                //修改定義中的name屬性值
                propertyValues.addPropertyValue("name", "趙四");
                System.out.println("[MyBeanFactoryPostProcessor]postProcessBeanFactory方法中修改了name屬性初始值了");
                System.out.println(propertyValues.toString());
            }
        }
    }
}

  4.自定義BeanPostProcessor類:

@Component
public class MyBeanPostProcessor implements BeanPostProcessor {
    @Override
    public Object postProcessBeforeInitialization(Object bean,
                                                  String beanName) throws BeansException {
        System.out.println("[MyBeanPostProcessor]後置處理器處理bean=【" + beanName + "】開始");
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean,
                                                 String beanName) throws BeansException {
        System.out.println("[MyBeanPostProcessor]後置處理器處理bean=【" + beanName + "】完畢!");
        return bean;
    }
}

   5.測試:

    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ExtConfig.class);
        Person bean = context.getBean(Person.class);
        System.out.println(bean.toString());
        context.close();
    }
    
======運行結果======
[MyBeanFactoryPostProcessor]調用了postProcessBeanFactory
[MyBeanFactoryPostProcessor]當前beanFactory共有9個bean
[MyBeanFactoryPostProcessor]當前beanFactory有下面組件[org.springframework.context.annotation.internalConfigurationAnnotationProcessor, org.springframework.context.annotation.internalAutowiredAnnotationProcessor, org.springframework.context.annotation.internalCommonAnnotationProcessor, org.springframework.context.event.internalEventListenerProcessor, org.springframework.context.event.internalEventListenerFactory, extConfig, myBeanFactoryPostProcessor, myBeanPostProcessor, person]
PropertyValues: length=0
[MyBeanFactoryPostProcessor]postProcessBeanFactory方法中修改了name屬性初始值了
PropertyValues: length=1; bean property 'name'
[MyBeanPostProcessor]後置處理器處理bean=【extConfig】開始
[MyBeanPostProcessor]後置處理器處理bean=【extConfig】完畢!
Person有參構造器:[name=張三,sex=男]
[Person]調用了BeanNameAware的setBeanName方法了:person
[Person]調用了BeanFactoryAware的setBeanFactory方法了:org.springframework.beans.factory.support.DefaultListableBeanFactory@e45f292: defining beans [org.springframework.context.annotation.internalConfigurationAnnotationProcessor,org.springframework.context.annotation.internalAutowiredAnnotationProcessor,org.springframework.context.annotation.internalCommonAnnotationProcessor,org.springframework.context.event.internalEventListenerProcessor,org.springframework.context.event.internalEventListenerFactory,extConfig,myBeanFactoryPostProcessor,myBeanPostProcessor,person]; root of factory hierarchy
[MyBeanPostProcessor]後置處理器處理bean=【person】開始
[Person]調用了Initailization的afterPropertiesSet方法了
[MyBeanPostProcessor]後置處理器處理bean=【person】完畢!
Person [name=趙四, sex=null]
[Person]調用了DisposableBean的destroy方法了

   從上面的運行結果能夠看出:

    1)Person的name值由"張三"變爲"趙四";

    2)BeanFactoryPostProcessor方法執行順序先於BeanPostProcessor接口中方法,且在bean實例化以前執行;

    3)BeanFactoryPostProcessor改變bean的定義,實例化出來的對象變了:「Person有參構造器:[name=張三,sex=男] 」變成了「Person [name=趙四, sex=null]

    4)BeanPostProcessor在bean建立對象實例化後,初始化(bean執行afterPropertiesSet方法或init-method方法)先後進行攔截工做;

 三.原理

   接下來咱們經過debug代碼來查看BeanFactoryPostProcessor的執行流程,從AbstractApplicationContext類的構造器方法看起,這裏面對應着容器初始化的基本操做;

  1.在測試main方法中下面的代碼打斷點:

AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ExtConfig.class);

  2.從下圖能夠看出容器先註冊配置類ExtConfig的定義信息,而後進行refresh刷新容器;

 

  3.先來看看register(componentClasses)註冊流程:從class文件讀取信息解析成beanDefinition

AnnotationConfigApplicationContextpublic void register(Class<?>... componentClasses) {
        Assert.notEmpty(componentClasses, "At least one component class must be specified");
        this.reader.register(componentClasses);
    }


AnnotatedBeanDefinitionReader:註冊beanDefinition
    public void register(Class<?>... componentClasses) {
        for (Class<?> componentClass : componentClasses) {
            registerBean(componentClass);
        }
    }
    
    public void registerBean(Class<?> beanClass) {
        doRegisterBean(beanClass, null, null, null, null);
    }
        
    //Register a bean from the given bean class, deriving its metadata from  class-declared annotations.
    //從class文件中讀取bean的定義信息,並註冊到容器中
    private <T> void doRegisterBean(Class<T> beanClass, @Nullable String name,
        @Nullable Class<? extends Annotation>[] qualifiers, @Nullable Supplier<T> supplier,
        @Nullable BeanDefinitionCustomizer[] customizers) {
        //獲得bean的全部定義信息:元數據metadata、做用域scope、初始化方法名字initMethodName等等
        AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(beanClass);
        if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) {
            return;
        }
        //爲bean實例建立一個特殊的回調信號
        abd.setInstanceSupplier(supplier);
        //獲取做用域的數據:單例
        ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);
        //設置bean爲單例
        abd.setScope(scopeMetadata.getScopeName());
        //獲取beanName
        String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry));
        //處理一些註釋信息:lazyInit、primary、dependsOn、role、description
        AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);
        if (qualifiers != null) {//qualifiers = nul 跳過
            for (Class<? extends Annotation> qualifier : qualifiers) {
                if (Primary.class == qualifier) {
                    abd.setPrimary(true);
                }
                else if (Lazy.class == qualifier) {
                    abd.setLazyInit(true);
                }
                else {
                    abd.addQualifier(new AutowireCandidateQualifier(qualifier));
                }
            }
        }
        if (customizers != null) {//customizers = null跳過
            for (BeanDefinitionCustomizer customizer : customizers) {
                customizer.customize(abd);
            }
        }
        //建立一個BeanDefinitionHolder
        BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);
        definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
        //容器中註冊beanDefinition
        BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
    }

  4.refresh刷新容器:invokeBeanFactoryPostProcessors方法用來找出全部beanFactory後置處理器,而且調用這些處理器來改變bean的定義

    public void refresh() throws BeansException, IllegalStateException {
        //來個鎖,否則 refresh() 還沒結束,你又來個啓動或銷燬容器的操做,那不就亂套了嘛
        synchronized (this.startupShutdownMonitor) {
            // Prepare this context for refreshing.
            //容器刷新前的處理方法:獲取啓動的系統時間、設置active活躍標識、開始打印日誌、設置環境變量、設置容器監聽器、設置容器事件
            prepareRefresh();

            // Tell the subclass to refresh the internal bean factory.
            //刷新bean工廠並獲取到bean工廠
            ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

            // Prepare the bean factory for use in this context.
            // bean工廠的初始化操做:設置類加載器、設置bean表達式解析器、設置bean後置處理器等等;
            prepareBeanFactory(beanFactory);

            try {
                // Allows post-processing of the bean factory in context subclasses.
                // 【這裏須要知道 BeanFactoryPostProcessor 這個知識點,Bean 若是實現了此接口,
                // 那麼在容器初始化之後,Spring 會負責調用裏面的 postProcessBeanFactory 方法。】
                 // 這裏是提供給子類的擴展點,到這裏的時候,全部的 Bean 都加載、註冊完成了,可是都尚未初始化
                 // 具體的子類能夠在這步的時候根據自身業務添加或修改一些特殊的 beanFactory屬性
                postProcessBeanFactory(beanFactory);

                // Invoke factory processors registered as beans in the context.
                //找出全部beanFactory後置處理器,而且調用這些處理器來改變bean的定義
 invokeBeanFactoryPostProcessors(beanFactory);

                // Register bean processors that intercept bean creation.
//註冊bean後置處理器
registerBeanPostProcessors(beanFactory); // Initialize message source for this context.
//初始化容器的信息源
initMessageSource(); // Initialize event multicaster for this context.
//初始化事件監聽多路廣播器
initApplicationEventMulticaster(); // Initialize other special beans in specific context subclasses.
//是個空殼方法,在AnnotationApplicationContex上下文中沒有實現,可能在spring後面的版本會去擴展。
//與Web上下文有關
onRefresh(); // Check for listener beans and register them. //註冊監聽器 registerListeners(); // Instantiate all remaining (non-lazy-init) singletons. //對象的建立:初始化剩下全部的(非懶加載的)單實例對象【從這裏能夠看出beanFactory後置處理器在初始化其餘組件以前執行】 finishBeanFactoryInitialization(beanFactory); // Last step: publish corresponding event.
//刷新完成工做,包括初始化LifecycleProcessor,發佈刷新完成事件等
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.
//銷燬已經初始化的 singleton 的 Beans,以避免有些 bean 會一直佔用資源
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(); } } }

  5.打開invokeBeanFactoryPostProcessors方法,以下所示,實際操做是委託PostProcessorRegis

trationDelegate去完成的:調用getBeanFactoryPostProcessors()方法獲取手工註冊到ApplicationCon

text的容器後置處理器集合

    protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
        PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());

        // Detect a LoadTimeWeaver and prepare for weaving, if found in the meantime
        // (e.g. through an @Bean method registered by ConfigurationClassPostProcessor)
        if (beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
            beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
            beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
        }
    } 

  1)在調用PostProcessorRegistrationDelegate類的invokeBeanFactoryPostProcessors方法時,注意第二個入參是getBeanFactoryPostProcessors()方法,該方法返回的是applicationContext的成員變量beanFactoryPostProcessors,該成員變量的值來自AbstractApplicationContext.addBeanFactoryPostProcessor方法被調用的時候:

    private final List<BeanFactoryPostProcessor> beanFactoryPostProcessors = new ArrayList<>();
    @Override
    public void addBeanFactoryPostProcessor(BeanFactoryPostProcessor postProcessor) {
        Assert.notNull(postProcessor, "BeanFactoryPostProcessor must not be null");
        this.beanFactoryPostProcessors.add(postProcessor);
    }

    public List<BeanFactoryPostProcessor> getBeanFactoryPostProcessors() {
        return this.beanFactoryPostProcessors;
    }

    2)AbstractApplicationContext.addBeanFactoryPostProcessor方法是留給業務擴展時調用的,例如在springboot初始化時,ConfigurationWarningsApplicationContextInitializer類的initialize方法中就有調用:

@Override
public void initialize(ConfigurableApplicationContext context) {
    context.addBeanFactoryPostProcessor(
            new ConfigurationWarningsPostProcessor(getChecks()));
}

6.看過了如何添加BeanFactoryPostProcessor,再回到PostProcessorRegistrationDelegate.invok

eBeanFactoryPostProcessors方法:實例化並調用全部已註冊的BeanFactoryPostProcessor bean;

流程是:

  1)beanFactory是BeanDefinitionRegistry類型時,此條件下完成以下流程:

    1.遍歷傳入後置處理器集合查找類型爲BeanDefinitionRegistryPostProcessor的後置處理器,調用後置處理器的postProcessBeanDefinitionRegistry方法;

    2.在容器中查找全部的實現了PriorityOrdered接口的BeanDefinition

RegistryPostProcessor集合,對後置處理器集合排序,遍歷,執行後置處理的postProcessBeanDefinitionRegistry方法;

    3.在容器中查找全部實現了Ordered接口的BeanDefinitionRegistryPostProcessor集合,對後置處理器集合排序,遍歷,執行後置處理的postProcessBeanDefinitionRegistry方法;

    4.在容器中查找其它(未實現排序接口)的BeanDefinitionRegistryPostProcessor並添加到集合nonOrderedPostProcessors中,對後置處理器集合排序,遍歷,執行後置處理的postProcessBeanDefinitionRegistry方法;

    5.當前全部的BeanDefinitionRegistryPostProcessor處理器的方法postProcessBeanD

efinitionRegistry 執行完畢後,執行其父類postProcessBeanFactory方法;

    6.執行全部非BeanDefinitionRegistryPostProcessor類型的後置處理器的postProcessB

eanFactory方法;

    PS:BeanDefinitionRegistryPostProcessor的簡介(BeanDefinitionRegistryPostProc

essor的實現案例請查看下文第7點的後文)

     (1)咱們開發的類,若是想註冊到spring容器,讓spring來完成實例化,經常使用方式以下:xml中經過bean節點來配置;使用@Service、@Controller、@Conponent等註解;
      其實,除了以上方式,spring還支持咱們經過代碼來將指定的類註冊到spring容器中,即便用BeanDefinitionRegistryPostProcessor來進行bean的註冊;

    (2)BeanDefinitionRegistryPostProcessor是BeanFactoryPostProcessor的子類,執行順序優先於BeanFactoryPostProcessor,執行流程跟BeanFactoryPostProcessor同樣,只是會先執行postProcessBeanDefinitionRegistry再執行postProcessBeanFactory;

    (3)BeanDefinitionRegistry提供了豐富的方法來操做bean定義,判斷、註冊、反註冊等方法都準備好了,咱們在編寫postProcessBeanDefinitionRegistry方法的內容時,就能直接使用入參registry的這些方法來完成判斷和註冊、反註冊等操做;

public interface BeanDefinitionRegistryPostProcessor extends BeanFactoryPostProcessor {

    //執行時機:在全部bean定義信息將要被加載,bean實例還未建立,利用下面方法給容器再額外添加一些組件
    void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException;

}

  2)beanFactory非BeanDefinitionRegistry類型時,此條件下完成以下流程:

    1.遍歷傳入後置處理器集合,執行後置處理器的postProcessBeanFactory方法;

    2.在容器中(beanFactory.getBeanNamesForType)查找全部的實現了PriorityOrdered接口的BeanFactoryPostProcessor集合,對後置處理器集合排序,遍歷,執行後置處理;

    3.在容器中查找全部實現了Ordered接口的BeanFactoryPostProcessor集合,對後置處理器集合排序,遍歷,執行後置處理;

    4.在容器中查找其它(未實現排序接口)的BeanFactoryPostProcessor並添加到集合nonOrderedPostProcessors中,對後置處理器集合排序,遍歷,執行後置處理;

    public static void invokeBeanFactoryPostProcessors(
            ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {

        // Invoke BeanDefinitionRegistryPostProcessors first, if any.
        Set<String> processedBeans = new HashSet<>();
        //若是beanFactory實現了BeanDefinitionRegistry
        if (beanFactory instanceof BeanDefinitionRegistry) {
            BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
            List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>();
            List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>();

            for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
                //若是beanFactoryPostProcessor實現了BeanDefinitionRegistryPostProcessor,分別放入兩個集合:registryProcessors 和 regularPostProcessors
                if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
                    BeanDefinitionRegistryPostProcessor registryProcessor =
                            (BeanDefinitionRegistryPostProcessor) postProcessor;
                    registryProcessor.postProcessBeanDefinitionRegistry(registry);
                    registryProcessors.add(registryProcessor);
                }
                else {
                    regularPostProcessors.add(postProcessor);
                }
            }

            // Do not initialize FactoryBeans here: We need to leave all regular beans
            // uninitialized to let the bean factory post-processors apply to them!
            // Separate between BeanDefinitionRegistryPostProcessors that implement
            // PriorityOrdered, Ordered, and the rest.
            List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();

            // First, invoke the BeanDefinitionRegistryPostProcessors that implement PriorityOrdered.
            //找出全部實現了BeanDefinitionRegistryPostProcessor接口和PriorityOrdered接口的bean,放入registryProcessors集合,
            //放入根據Set接口來排序,而後這些bean會被invokeBeanDefinitionRegistryPostProcessors方法執行;
            String[] postProcessorNames =
                    beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
            for (String ppName : postProcessorNames) {
                if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
                    currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
                    processedBeans.add(ppName);
                }
            }
            sortPostProcessors(currentRegistryProcessors, beanFactory);
            registryProcessors.addAll(currentRegistryProcessors);
            invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
            currentRegistryProcessors.clear();

            // Next, invoke the BeanDefinitionRegistryPostProcessors that implement Ordered.
            //找出全部實現了BeanDefinitionRegistryPostProcessor接口和Ordered接口的bean,放入registryProcessors集合,
            //放入根據Set接口來排序,而後這些bean會被invokeBeanDefinitionRegistryPostProcessors方法執行;
            postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
            for (String ppName : postProcessorNames) {
                if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) {
                    currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
                    processedBeans.add(ppName);
                }
            }
            sortPostProcessors(currentRegistryProcessors, beanFactory);
            registryProcessors.addAll(currentRegistryProcessors);
            invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
            currentRegistryProcessors.clear();

            // Finally, invoke all other BeanDefinitionRegistryPostProcessors until no further ones appear.
            //對於那些實現了BeanDefinitionRegistryPostProcessor接口,可是沒有實現PriorityOrdered和Ordered的bean也被找出來,
            //而後這些bean會被invokeBeanDefinitionRegistryPostProcessors方法執行;
            boolean reiterate = true;
            while (reiterate) {
                reiterate = false;
                postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
                for (String ppName : postProcessorNames) {
                    if (!processedBeans.contains(ppName)) {
                        currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
                        processedBeans.add(ppName);
                        reiterate = true;
                    }
                }
                sortPostProcessors(currentRegistryProcessors, beanFactory);
                registryProcessors.addAll(currentRegistryProcessors);
                invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
                currentRegistryProcessors.clear();
            }

            // Now, invoke the postProcessBeanFactory callback of all processors handled so far.
            //registryProcessors和regularPostProcessors集合被invokeBeanFactoryPostProcessors執行
            invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
            invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
        }

        else {
            // Invoke factory processors registered with the context instance.
            //入參中的BeanFactoryPostProcessor,沒有實現BeanDefinitionRegistryPostProcessor的那些bean,被invokeBeanFactoryPostProcessors執行
            invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);
        }

        // Do not initialize FactoryBeans here: We need to leave all regular beans
        // uninitialized to let the bean factory post-processors apply to them!
        String[] postProcessorNames =
                beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);

        // Separate between BeanFactoryPostProcessors that implement PriorityOrdered,
        // Ordered, and the rest.
        //找出實現了BeanFactoryPostProcessor接口的bean,注意這裏已將上面實現了BeanDefinitionRegistryPostProcessor接口的bean給剔除了,
        //將這些bean分爲三類:實現了PriorityOrdered接口的放入priorityOrderedPostProcessors,
        //實現了Ordered接口的放入orderedPostProcessorNames,其餘的放入nonOrderedPostProcessorNames
        //自定義的實現BeanFactoryPostProcessor接口的bean就會在nonOrderedPostProcessorNames被找出來
        List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
        List<String> orderedPostProcessorNames = new ArrayList<>();
        List<String> nonOrderedPostProcessorNames = new ArrayList<>();
        for (String ppName : postProcessorNames) {
            if (processedBeans.contains(ppName)) {
                // skip - already processed in first phase above
            }
            else if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
                priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));
            }
            else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
                orderedPostProcessorNames.add(ppName);
            }
            else {
                nonOrderedPostProcessorNames.add(ppName);
            }
        }

        // First, invoke the BeanFactoryPostProcessors that implement PriorityOrdered.
        //priorityOrderedPostProcessors先排序再被invokeBeanFactoryPostProcessors執行
        sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
        invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);

        // Next, invoke the BeanFactoryPostProcessors that implement Ordered.
        //orderedPostProcessorNames先被遍歷加入到orderedPostProcessors,再被排序,最後才被invokeBeanFactoryPostProcessors執行
        List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size());
        for (String postProcessorName : orderedPostProcessorNames) {
            orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
        }
        sortPostProcessors(orderedPostProcessors, beanFactory);
        invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);

        // Finally, invoke all other BeanFactoryPostProcessors.
        //nonOrderedPostProcessorNames也是先被遍歷到nonOrderedPostProcessors,再被invokeBeanFactoryPostProcessors執行
        List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size());
        for (String postProcessorName : nonOrderedPostProcessorNames) {
            nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
        }
        //這時纔是執行自定義BeanFactoryPostProcessor的postProcessBeanFactory
 invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);

        // Clear cached merged bean definitions since the post-processors might have
        // modified the original metadata, e.g. replacing placeholders in values...
        beanFactory.clearMetadataCache();
    }
    • getBeanNamesForType():根據傳遞的類型獲取容器中的beanName
      // type:類的類型名稱
      // includeNonSingletons:返回數據包含了非單例beanName
      // allowEagerInit: 能夠提早加載初始化
      public String[] getBeanNamesForType(Class<?> type, boolean includeNonSingletons, boolean allowEagerInit) {
          if (!isConfigurationFrozen() || type == null || !allowEagerInit) {
             // 不可用緩存、類型無效、不容許提早加載初始化
             // 須要獲取當前type的原始類型,繼續獲取數據
              return doGetBeanNamesForType(ResolvableType.forRawClass(type), includeNonSingletons, allowEagerInit);
          }
          Map<Class<?>, String[]> cache =
                  (includeNonSingletons ? this.allBeanNamesByType : this.singletonBeanNamesByType);
          String[] resolvedBeanNames = cache.get(type);
          // 若是緩存已經存儲了該數據,則無需再計算,直接返回便可
          if (resolvedBeanNames != null) {
              return resolvedBeanNames;
          }
          resolvedBeanNames = doGetBeanNamesForType(ResolvableType.forRawClass(type), includeNonSingletons, true);
          // 這一步就是真正的獲取數據,遍歷beanDefinitionNames的每個數據,符合要求的就會加入到返回的列表中
          
          if (ClassUtils.isCacheSafe(type, getBeanClassLoader())) {
              cache.put(type, resolvedBeanNames);
              // 便於下一次獲取,加入緩存中
          }
          return resolvedBeanNames;
      }
    • getBean後面還有一個參數BeanFactoryPostProcessor.class,注意看這個函數,會發現返回的是一個抽象類,結論就是nonOrderedPostProcessors添加的不是bean實例,而是beandefinition,在實例化前。
  7.從上面代碼中能夠看出全部實現了BeanFactoryPostProcessor接口的bean,都被做爲入參,而後調用了invokeBeanDefinitionRegistryPostProcessors或者invokeBeanFactoryPostProcessors方法去處理:對每一個BeanFactoryPostProcessor接口的實現類,都調用了其接口方法,不一樣的是,對於實現了BeanDefinitionRegistryPostProcessor接口的bean,調用其post ProcessBean DefinitionRegistry方法的時候,入參是BeanDefinitionRegistry,而非BeanFactory,所以,實現了BeanDefinitionRegistryPostProcessor接口的bean,其postProcessBeanDefinitionRegistry在被調用時,能夠經過入參BeanDefinitionRegistry來作更多和bean的定義有關的操做,例如註冊bean;
    /**
     * Invoke the given BeanDefinitionRegistryPostProcessor beans.
     */
    private static void invokeBeanDefinitionRegistryPostProcessors(
            Collection<? extends BeanDefinitionRegistryPostProcessor> postProcessors, BeanDefinitionRegistry registry) {

        for (BeanDefinitionRegistryPostProcessor postProcessor : postProcessors) {
            postProcessor.postProcessBeanDefinitionRegistry(registry);
        }
    }
        
    /**
     * Invoke the given BeanFactoryPostProcessor beans.
     */    
    private static void invokeBeanFactoryPostProcessors(
        Collection<? extends BeanFactoryPostProcessor> postProcessors, ConfigurableListableBeanFactory beanFactory) {

        for (BeanFactoryPostProcessor postProcessor : postProcessors) {
            postProcessor.postProcessBeanFactory(beanFactory);
        }
    } 
    • BeanDefinitionRegistryPostProcessor案例實現:在上面案例中多添加一個BeanDefinitionRegistryPostProcessor實現類
      @Configuration
      public class MyBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor {
      
      
          @Override
          public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
              System.out.println("[MyBeanDefinitionRegistryPostProcessor]postProcessBeanFactory--->bean的數量:" + beanFactory.getBeanDefinitionCount());
      
          }
      
          @Override
          public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
              System.out.println("[MyBeanDefinitionRegistryPostProcessor]postProcessBeanDefinitionRegistry--->bean的數量:" + registry.getBeanDefinitionCount());
              //給容器註冊bean
              //RootBeanDefinition beanDefinition = new RootBeanDefinition(Color.class);
              AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.rootBeanDefinition(Color.class).getBeanDefinition();
              registry.registerBeanDefinition("color",beanDefinition);
          }
      }
      =========測試執行結果=========
      [MyBeanDefinitionRegistryPostProcessor]postProcessBeanDefinitionRegistry--->bean的數量:10
      十一月 02, 2020 7:26:46 下午 org.springframework.context.annotation.ConfigurationClassPostProcessor enhanceConfigurationClasses
      信息: Cannot enhance @Configuration bean definition 'myBeanDefinitionRegistryPostProcessor' since its singleton instance has been created too early. The typical cause is a non-static @Bean method with a BeanDefinitionRegistryPostProcessor return type: Consider declaring such methods as 'static'.
      [MyBeanDefinitionRegistryPostProcessor]postProcessBeanFactory--->bean的數量:11
      [MyBeanFactoryPostProcessor]調用了postProcessBeanFactory
      [MyBeanFactoryPostProcessor]當前beanFactory共有11個bean
      [MyBeanFactoryPostProcessor]當前beanFactory有下面組件[org.springframework.context.annotation.internalConfigurationAnnotationProcessor, org.springframework.context.annotation.internalAutowiredAnnotationProcessor, org.springframework.context.annotation.internalCommonAnnotationProcessor, org.springframework.context.event.internalEventListenerProcessor, org.springframework.context.event.internalEventListenerFactory, extConfig, myBeanDefinitionRegistryPostProcessor, myBeanFactoryPostProcessor, myBeanPostProcessor, person, color]
      PropertyValues: length=0
      [MyBeanFactoryPostProcessor]postProcessBeanFactory方法中修改了name屬性初始值了
      PropertyValues: length=1; bean property 'name'
      [MyBeanPostProcessor]後置處理器處理bean=【extConfig】開始
      [MyBeanPostProcessor]後置處理器處理bean=【extConfig】完畢!
      Person有參構造器:[name=張三,sex=男]
      [Person]調用了BeanNameAware的setBeanName方法了:person
      [Person]調用了BeanFactoryAware的setBeanFactory方法了:org.springframework.beans.factory.support.DefaultListableBeanFactory@e45f292: defining beans [org.springframework.context.annotation.internalConfigurationAnnotationProcessor,org.springframework.context.annotation.internalAutowiredAnnotationProcessor,org.springframework.context.annotation.internalCommonAnnotationProcessor,org.springframework.context.event.internalEventListenerProcessor,org.springframework.context.event.internalEventListenerFactory,extConfig,myBeanDefinitionRegistryPostProcessor,myBeanFactoryPostProcessor,myBeanPostProcessor,person,color]; root of factory hierarchy
      [MyBeanPostProcessor]後置處理器處理bean=【person】開始
      [Person]調用了Initailization的afterPropertiesSet方法了
      [MyBeanPostProcessor]後置處理器處理bean=【person】完畢!
      [MyBeanPostProcessor]後置處理器處理bean=【color】開始
      [MyBeanPostProcessor]後置處理器處理bean=【color】完畢!
      Person [name=趙四, sex=null]
      [Person]調用了DisposableBean的destroy方法了

  8.BeanFactoryPostProcessor 執行的總體流程:

    1)ApplicationContext的refresh方法

    2)ApplicationContext的invokeBeanFactoryPostProcessors方法

    3)PostProcessorRegistrationDelegate的invokeBeanFactoryPostProcessors

  9.BeanFactoryPostProcessor執行的優先級:

    1)首先是實現了PriorityOrdered接口的,排序執行

    2)下來是實現了Ordered接口的,排序執行

    3)最後是其它(未實現排序接口),順序執行

  10.BeanFactoryPostProcessor獲取機制:

    1)首先獲取手動註冊ApplicationContext的集合

    2)再次是經過beanFactory.getBeanNamesForType查找全部已註冊的BeanFactory

PostProcessor的bean定義並實例化。

四.總結

  1. ApplicationContext擴展類能夠調用AbstractApplicationContext.addBeanFactoryPostProcessor方法,將自定義的BeanFactoryPostProcessor實現類保存到ApplicationContext中;
  2. Spring容器初始化時,上一步中被加入到ApplicationContext的bean會被優先調用其postProcessBeanFactory方法;
  3. 自定義的BeanFactoryPostProcessor接口實現類,也會被找出來,而後調用其postProcessBeanFactory方法;
  4. postProcessBeanFactory方法被調用時,beanFactory會被做爲參數傳入,自定義類中可使用該參數來處理bean的定義,達到業務需求;
  5. 此時的Spring容器尚未開始實例化bean,所以自定義的BeanFactoryPostProcessor實現類不要作與bean實例有關的操做,而是作一些與bean定義有關的操做,例如修改某些字段的值,這樣後面實例化的bean的就會有相應的改變

   6.Spring主要將BeanFactoryPostProcessor劃分了兩類:

    • 正常的BeanFactoryPostProcessor
    • BeanDefinitionRegistry類型的BeanDefinitionRegistryPostProcessor

  7.在執行流程中能夠看到Spring先執行了BeanDefinitionRegistryPostProcessor類型的postProcessBeanDefinitionRegistry方法,再執行BeanDefinitionRegistryPostProcessor和正常BeanFactoryPostProcessor的postProcessBeanFactory方法。

  8.Spring對BeanDefinitionRegistryPostProcessor的解釋是:容許在正常的BeanFactoryPostProcessor執行檢測開始以前註冊更多的自定義bean。也就是說BeanDefinitionRegistryPostProcessor的方法postProcessBeanDefinitionRegistry能夠在後置處理器執行前自定義註冊更多的BeanDefinition

  例如:Spring實現的ConfigurationClassPostProcessor用於註冊註解@Configuration標識的類裏面定義的BeanDefinition。

相關文章
相關標籤/搜索