Spring裝配Bean--源碼學習

1. 詳解Spring 中如何控制2個bean中的初始化順序

??開發過程中有這樣一個場景,2個 bean 初始化邏輯中有依賴關系,需要控制二者的初始化順序。實現方式可以有多種,本文結合目前對 Spring 的理解,嘗試列出幾種思路。
場景
假設A,B兩個 bean 都需要在初始化的時候從本地磁盤讀取文件,其中B加載的文件,依賴A中加載的全局配置文件中配置的路徑,所以需要A先于B初始化,此外A中的配置改變后也需要觸發B的重新加載邏輯,所以A,B需要注入彼此。
對于下面的模型,問題簡化為:我們需要initA()先于initB()得到執行。

image

1.1 方案一:立Flag

??可以在業務層自己控制A,B的初始化順序,在A中設置一個“是否初始化的”標記,B初始化前檢測A是否得以初始化,如果沒有則調用A的初始化方法,所謂的check-and-act。對于上述模型,實現如下:

image

[站外圖片上傳中...(image-a48682-1551843463104)]
執行效果:

A construct
B construct
A init
B init

??這種立flag的方法好處是可以做到lazy initialization,但是如果類似邏輯很多的話代碼中到處充斥著類似代碼,不優雅,所以考慮是否框架本身就可以滿足我們的需要。

1.2 方案二:使用DependsOn

??Spring 中的 DependsOn 注解可以保證被依賴的bean先于當前bean被容器創建,但是如果不理解Spring中bean加載過程會對 DependsOn 有誤解;

1.3方案三:容器加載bean之前

??Spring 框架中很多地方都為我們提供了擴展點,很好的體現了開閉原則(OCP)。其中 BeanFactoryPostProcessor 可以允許我們在容器加載任何bean之前修改應用上下文中的BeanDefinition(從XML配置文件或者配置類中解析得到的bean信息,用于后續實例化bean)。

??在本例中,就可以把A的初始化邏輯放在一個 BeanFactoryPostProcessor 中。
[站外圖片上傳中...(image-8c8fa4-1551843463104)]

執行效果:

A init
A construct
B construct
B init

??這種方式把A中的初始化邏輯放到了加載bean之前,很適合加載系統全局配置,但是這種方式中初始化邏輯不能依賴bean的狀態。

1.4 方案四:事件監聽器的有序性

??Spring 中的 Ordered 也是一個很重要的組件,很多邏輯中都會判斷對象是否實現了 Ordered 接口,如果實現了就會先進行排序操作。比如在事件發布的時候,對獲取到的 ApplicationListener 會先進行排序。
所以可以利用事件監聽器在處理事件時的有序性,在應用上下文 refresh 完成后,分別實現A,B中對應的初始化邏輯。

image
image

2. Spring裝配Bean的過程

?? Spring裝配Bean的過程

1. 實例化;
2. 設置屬性值;
3. 如果實現了BeanNameAware接口,調用setBeanName設置Bean的ID或者Name;
4. 如果實現BeanFactoryAware接口,調用setBeanFactory 設置BeanFactory;
5. 如果實現ApplicationContextAware,調用setApplicationContext設置ApplicationContext
6. 調用BeanPostProcessor的預先初始化方法;
7. 調用InitializingBean的afterPropertiesSet()方法;
8. 調用定制init-method方法;
9. 調用BeanPostProcessor的后初始化方法;

分析:
spring的兩個核心接口BeanFactory和ApplicationContext。BeanFactory主要定義容器的核心方法,ApplicationContext加以擴展,主要使用的還是ApplicationContext。在ApplicationContext的子類中,AbstractApplicationContext中的refresh()方法定義了容器加載配置文件及裝配Bean的過程。
AbstractApplicationContext#refresh()代碼如下:

image

容器在啟動之前要獲得對象鎖,保證容器只有一個啟動synchronized

/容器在啟動之前要獲得對象鎖,保證容器只有一個啟動synchronized

//1 準備刷新工作,刷新前的預處理
prepareRefresh();

// 2 實例化BeanFactory,將配置文件的信息裝入到容器的Bean定義的注冊表(BeanDefinitionRegistry中),此時Bean還未初始化
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

// 3 準備BeanFactory 主要是加載一些類,
prepareBeanFactory(beanFactory);
try {
    // 4 留作子類實現
    //抽象的方法,當前未做處理。子類通過重寫這個方法來在BeanFactory創建并預準備完成以后做進一步的設置
    postProcessBeanFactory(beanFactory);
    /*******以上是BeanFactory的創建及預準備工作*****/
        
    // 5 調用工廠后處理器
    invokeBeanFactoryPostProcessors(beanFactory);
    
    //6 注冊bean后處理器,注冊BeanPostProcessor(Bean的后置處理器)
    registerBeanPostProcessors(beanFactory);
    
    //7 初始化消息源,初始化MessageSource組件(做國際化功能;消息綁定,消息解析);
    initMessageSource();
    
    //8 初始化事件廣播器
    initApplicationEventMulticaster();
    
    //9 鉤子方法
    onRefresh();
    
    // 10 注冊監聽器,給容器中將所有項目里面的ApplicationListener注冊進來
 
    registerListeners();
    
    //11 完成bean實例化(除lazy-init),并放入緩存中,
    //   初始化所有剩下的單實例bean;
    finishBeanFactoryInitialization(beanFactory);
    
    // 12 廣播刷新事件,完成BeanFactory的初始化創建工作;IOC容器就創建完成;
    finishRefresh();
}

refresh()函數的重點步驟:

2.1 prepareRefresh():刷新前的預處理;

image

??initPropertySources()是初始化上下文環境,容器的一些信息這個時候加載了進來比如文件路徑信息;getEnvironment().validateRequiredProperties()
查看標示為必填的屬性信息是否都有了,校驗配置文件的屬性和合法性。

2.2 obtainFreshBeanFactory:實例化beanFactory

image

??查看refreshBeanFactorybeanFactory創造過程。繼續追蹤到AbstractApplicationContext的子類:
AbstractRefreshableApplicationContext
??refreshBeanFactory

  1. 先判斷是否已經存在BeanFactory,如果存在,則銷毀所有的bean,并關閉beanFactory;防止重復加載beanFactory
  2. 創建一個beanFactory(類型為DefalutListableBeanFactory),最重要的BeanFactory;spring注冊及加載bean就靠它。其實這里還是一個基本的容器
  3. 初始化XmlBeanDefinitionReader用來讀取xml,并加載解析
  4. 設置為全局變量,AbstractRefreshableApplicationContext持有DefaultListableBeanFactory引用
image

customizeBeanFactory,在類AbstractRefreshableApplicationContext中,這里是根據AbstractRefreshableApplicationContext類的屬性為Beanfactory設置值。

image

allowBeanDefinitionOverriding屬性是指是否允對一個名字相同但definition不同進行重新注冊,默認是true。 allowCircularReferences屬性是指是否允許Bean之間循環引用,默認是true.
默認情況下兩個屬性都為空,既然是可擴展的,那么自然可以自己設置屬性,方法就是繼承ClassPathXmlApplicationContext并復寫customizeBeanFactory方法為兩個屬性設置值即可。

2.3 prepareBeanFactory:BeanFactory的預準備工作

protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
    // 1)、設置BeanFactory的類加載器
    beanFactory.setBeanClassLoader(getClassLoader());
    // 1)、設置支持表達式解析器
    beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
    beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));
?
    // 2)、添加部分BeanPostProcessor【ApplicationContextAwareProcessor】
    beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
    // 3)、設置忽略的自動裝配的接口EnvironmentAware、EmbeddedValueResolverAware、xxx;
   // 這些接口的實現類不能通過類型來自動注入
    beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
    beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
    beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
    beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
    beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
    beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);
?
    // 4)、注冊可以解析的自動裝配;我們能直接在任何組件中自動注入:
    //BeanFactory、ResourceLoader、ApplicationEventPublisher、ApplicationContext
    /* 其他組件中可以通過下面方式直接注冊使用
    @autowired 
    BeanFactory beanFactory */
    beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
    beanFactory.registerResolvableDependency(ResourceLoader.class, this);
    beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
    beanFactory.registerResolvableDependency(ApplicationContext.class, this);
?
    // 5)、添加BeanPostProcessor【ApplicationListenerDetector】后置處理器,在bean初始化前后的一些工作; 
    // 將當前的ApplicationContext對象交給ApplicationContextAwareProcessor類來處理,從而在Aware接口實現類中的注入applicationContext

    beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));
?
    // 6)、添加編譯時的AspectJ;
    if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
        beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
        // Set a temporary ClassLoader for type matching.
        beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
    }
?
    // 7)、給BeanFactory中注冊一些能用的組件;
    if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {
    // 環境信息ConfigurableEnvironment
        beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());
    }
    //系統屬性,systemProperties【Map<String, Object>】
    if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {
        beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());
    }
    //系統環境變量systemEnvironment【Map<String, Object>】
    if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {
        beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());
    }
}

總結:

 1.設置類加載器;
 2.設置EL表達式解析器(Bean創建完成填充屬性時使用)和屬性注冊解析器
 3.利用BeanPostProcessor的特性給各種Aware接口的實現類注入ApplicationContext中對應的屬性
 4.設置各種Aware接口的實現類為忽略自動裝配
 5.設置自動裝配的類(BeanFactory,ResourceLoader,ApplicationEventPublisher,ApplicationContext)
 6.如果BeanFactory中存在loadTimeWeaver的bean,那么需要添加動態織入功能
 7.注冊各種可用組件(environment,systemProperties,systemEnvironment)

2.4 執行BeanFactoryPostProcessor的后置處理器方法(BeanFactory)

??Spring中BeanFactoryPostProcessorBeanPostProcessor都是Spring初始化bean時對外暴露的擴展點。兩個接口從名字看起來很相似,但是作用及使用場景卻不同。
??Spring IoC容器允許BeanFactoryPostProcessor在容器實例化任何bean之前讀取bean的定義(配置元數據),并可以修改它。同時可以定義多個BeanFactoryPostProcessor,通過設置'order'屬性來確定各個BeanFactoryPostProcessor執行順序。

?? 注冊一個BeanFactoryPostProcessor實例需要定義一個Java類來實現BeanFactoryPostProcessor接口,并重寫該接口的postProcessorBeanFactory方法。通過beanFactory可以獲取bean的定義信息,并可以修改bean的定義信息。這點是和BeanPostProcessor最大區別!
如下,Spring中bean工廠后置處理器也就是BeanFactoryPostProcessor接口:

image

??注釋可知允許我們在工廠里所有的bean被加載進來后但是還沒初始化前,對所有bean的屬性進行修改也可以add屬性值。
注意:
BeanFactoryPostProcessor可以與bean definitions打交道,但是千萬不要進行bean實例化(感覺這里應該說的是不要在BeanFactoryPostProcessor進行可能觸發bean實例化的操作)。這么做可能會導致bean被提前實例化,會破壞容器造成預估不到的副作用。如果你需要hack到bean實例化過程,請考慮使用BeanPostProcessor

??definitions進行一定hack,但是也僅此而已了。絕對不允許在BeanFactoryPostProcessor中觸發到bean的實例化!!!
doc說得很清楚but never bean instances. Doing so may cause premature bean instantiation, violating the container and causing unintended side-effects. 下面就列舉錯誤使用造成的兩種典型“副作用”。

錯誤1)使用注解進行依賴注入失敗


@Component
public class PrematureBeanFactoryPostProcessor implements BeanFactoryPostProcessor {

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        Map<String, BBean> map = beanFactory.getBeansOfType(BBean.class);
        for (BBean bBean : map.values()) {
            assert bBean.getABean() == null;
        }
    }
}

@Component("bBean")
public class BBean {

    @Autowired
    private ABean aBean;

    public ABean getABean() {
        return aBean;
    }

}

@Component
public class ABean {

    private String name = "a";

    public String getName() {
        return name;
    }

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

}

??從裝配bean的AbstractApplicationContext#refresh()方法中可以看到的是postProcessBeanFactory(beanFactory); 首先invoke了容器中的BeanFactoryPostProcessor實現類,其中當然就包括PrematureBeanFactoryPostProcessor,此時通過beanFactory.getBeansOfType觸發了bean提前實例化。
??按理說,bean提前實例化也應該沒問題的,aBean也應該是能夠被注入的呀!那為啥最終不是這個結果呢。讓我們研究下@Resource @AutoWired這種注解是如何注入依賴的,如何起作用的就明白了。
@AutoWired起作用依賴AutowiredAnnotationBeanPostProcessor, @Resource依賴CommonAnnotationBeanPostProcessor;
這倆都是BeanPostProcessor的實現。那BeanPostProcessors在何處被spring invoke呢,參見registerBeanPostProcessors(beanFactory);postProcessBeanFactory(beanFactory); 后面被調用,也就是說BBean被觸發提前初始化的時候,AutowiredAnnotationBeanPostProcessor還沒有被注冊自然也不會被執行到,自然ABean=null

Spring的BeanPostProcessor和BeanFactoryPostProcessor區別
BeanPostProcessor:bean級別的處理,針對某個具體的bean進行處理,bean實例化之后執行;能在spring容器實例化bean之后,在執行bean的初始化方法前后,添加一些自己的處理邏輯
BeanFactoryPostProcessor:是針對bean容器的,它的實現類可以在當前BeanFactory初始化(spring容器加載bean定義文件)后,bean實例化之前修改bean的定義屬性,達到影響之后實例化bean的效果。BeanFactory級別的處理,是針對整個Bean的工廠進行處理,bean實例化之前執行;Spring允許BeanFactoryPostProcessor在容器實例化任何其它bean之前讀取配置元數據,并可以根據需要進行修改,例如可以把bean的scope從singleton改為prototype,也可以把property的值給修改掉。可以同時配置多個BeanFactoryPostProcessor,并通過設置’order’屬性來控制各個BeanFactoryPostProcessor的執行次序。

2.5 registerBeanPostProcessors:注冊BeanPostProcessor(Bean的后置處理器)

registerBeanPostProcessors從名稱可以看出是用來注冊BeanPostProcessor的。下面是BeanPostProcessor的代碼,可以看出只有兩個方法。

BeanPostProcessor接口方法

postProcessBeforeInitialization作用:在bean實例化、依賴注入之后,初始化(顯示)之前執行。什么叫顯示初始化?我們知道在bean實例化之前,已經初始化對象了,這里顯示指的是,要給bean的某些屬性手動賦值,或手動去執行的某些方法。比如:init-method方法,其就是在實例化之后調用的。

postProcessAfterInitialization作用:在bean實例化、依賴注入之后,初始化(顯示)之后執行。

上面講到的BeanFactoryPostProcessor是用來處理bean工廠或者是bean定義的,BeanPostProcessor是用來處理bean實例的

public static void registerBeanPostProcessors(
    ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {
//1)、獲取所有的 BeanPostProcessor;后置處理器都默認可以通過PriorityOrdered、Ordered接口來執行優先級
    String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);
?
     //檢查器,檢查所有的BeanPostProcessor
    int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length;
    beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));
?
    // Separate between BeanPostProcessors that implement PriorityOrdered,
    // Ordered, and the rest.
    List<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList<BeanPostProcessor>();
    List<BeanPostProcessor> internalPostProcessors = new ArrayList<BeanPostProcessor>();
    List<String> orderedPostProcessorNames = new ArrayList<String>();
    List<String> nonOrderedPostProcessorNames = new ArrayList<String>();
    for (String ppName : postProcessorNames) {
        if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
            BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
            priorityOrderedPostProcessors.add(pp);
            if (pp instanceof MergedBeanDefinitionPostProcessor) {
                internalPostProcessors.add(pp);
            }
        }
        else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
            orderedPostProcessorNames.add(ppName);
        }
        else {
            nonOrderedPostProcessorNames.add(ppName);
        }
    }
?
  /*  2)、先注冊PriorityOrdered優先級接口的BeanPostProcessor;
            把每一個BeanPostProcessor;添加到BeanFactory中
            beanFactory.addBeanPostProcessor(postProcessor);*/
    sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
    registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);
?
    // 3)、再注冊Ordered接口的
    List<BeanPostProcessor> orderedPostProcessors = new ArrayList<BeanPostProcessor>();
    for (String ppName : orderedPostProcessorNames) {
        BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
        orderedPostProcessors.add(pp);
        if (pp instanceof MergedBeanDefinitionPostProcessor) {
            internalPostProcessors.add(pp);
        }
    }
    sortPostProcessors(orderedPostProcessors, beanFactory);
    registerBeanPostProcessors(beanFactory, orderedPostProcessors);
?
    // 4)、最后注冊沒有實現任何優先級接口的
    List<BeanPostProcessor> nonOrderedPostProcessors = new ArrayList<BeanPostProcessor>();
    for (String ppName : nonOrderedPostProcessorNames) {
        BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
        nonOrderedPostProcessors.add(pp);
        if (pp instanceof MergedBeanDefinitionPostProcessor) {
            internalPostProcessors.add(pp);
        }
    }
    registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors);
?
    // 5)、最終注冊MergedBeanDefinitionPostProcessor;
    sortPostProcessors(internalPostProcessors, beanFactory);
    registerBeanPostProcessors(beanFactory, internalPostProcessors);
?
    // 6)、注冊一個ApplicationListenerDetector;判斷創建完成的bean是否監聽器
   /* 在Bean創建完成后ApplicationListenerDetector.postProcessAfterInitialization()中檢查是否是ApplicationListener 類型,如果是applicationContext.addApplicationListener((ApplicationListener<?>) bean);如果是添加到容器中 */
    beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext));
}

2.6 initMessageSource();國際化

初始化MessageSource組件(做國際化功能;消息綁定,消息解析);

protected void initMessageSource() {
  // 1)、獲取BeanFactory
    ConfigurableListableBeanFactory beanFactory = getBeanFactory();
    /*  
    2)、看容器中是否有id為messageSource的,類型是MessageSource的組件
            如果有賦值給messageSource,如果沒有自己創建一個DelegatingMessageSource;
            MessageSource作用:取出國際化配置文件中的某個key的值;能按照區域信息獲取;
    */
    if (beanFactory.containsLocalBean(MESSAGE_SOURCE_BEAN_NAME)) {
        this.messageSource = beanFactory.getBean(MESSAGE_SOURCE_BEAN_NAME, MessageSource.class);
        // Make MessageSource aware of parent MessageSource.
        if (this.parent != null && this.messageSource instanceof HierarchicalMessageSource) {
            HierarchicalMessageSource hms = (HierarchicalMessageSource) this.messageSource;
            if (hms.getParentMessageSource() == null) {
                // Only set parent context as parent MessageSource if no parent MessageSource
                // registered already.
                hms.setParentMessageSource(getInternalParentMessageSource());
            }
        }
        if (logger.isDebugEnabled()) {
            logger.debug("Using MessageSource [" + this.messageSource + "]");
        }
    }
    else {
        // 如果沒有自己創建一個DelegatingMessageSource;
        DelegatingMessageSource dms = new DelegatingMessageSource();
        dms.setParentMessageSource(getInternalParentMessageSource());
        this.messageSource = dms;
        //把創建好的messageSource注冊到容器中,以后獲取國際化配置文件的值的時候,可以自動注入MessageSource; 
       //注入后通過這個方法使用MessageSource.getMessage(String code, Object[] args, String defaultMessage, Locale locale);
        beanFactory.registerSingleton(MESSAGE_SOURCE_BEAN_NAME, this.messageSource);
        if (logger.isDebugEnabled()) {
            logger.debug("Unable to locate MessageSource with name '" + MESSAGE_SOURCE_BEAN_NAME +
                         "': using default [" + this.messageSource + "]");
        }
    }
}

2.7 初始化事件派發器initApplicationEventMulticaster()

protected void initApplicationEventMulticaster() {
    //1)、獲取BeanFactory
    ConfigurableListableBeanFactory beanFactory = getBeanFactory();
    //判斷容器中是否有applicationEventMulticaster 的這個bean ,如果有獲取,沒有創建
    if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) {
        //2)、從BeanFactory中獲取applicationEventMulticaster的ApplicationEventMulticaster;
        this.applicationEventMulticaster =
            beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class);
        if (logger.isDebugEnabled()) {
            logger.debug("Using ApplicationEventMulticaster [" + this.applicationEventMulticaster + "]");
        }
    }
    else {
        //3) 個SimpleApplicationEventMulticaster 類型的 applicationEventMulticaster
        this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
        //4)、將創建的ApplicationEventMulticaster添加到BeanFactory中,以后其他組件直接自動注入
        beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster);
        if (logger.isDebugEnabled()) {
            logger.debug("Unable to locate ApplicationEventMulticaster with name '" +
                         APPLICATION_EVENT_MULTICASTER_BEAN_NAME +
                         "': using default [" + this.applicationEventMulticaster + "]");
        }
    }
}

2.8 onRefresh();留給子容器(子類)

類重寫AbstractApplicationContext.onRefresh()這個方法,在容器刷新的時候可以自定義邏輯;

2.9 registerListeners();檢查和注冊 Listener

將所有項目里面的ApplicationListener注冊到容器中;

protected void registerListeners() {
    //1、從容器中拿到所有的ApplicationListener
    for (ApplicationListener<?> listener : getApplicationListeners()) {
        //2、將每個監聽器添加到事件派發器中;
        getApplicationEventMulticaster().addApplicationListener(listener);
    }
    
    // 1.獲取所有的ApplicationListener
    String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
    for (String listenerBeanName : listenerBeanNames) {
        //2、將每個監聽器添加到事件派發器中;
        getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
    }
?
    // earlyApplicationEvents 中保存之前的事件,
    Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;
    this.earlyApplicationEvents = null;
    if (earlyEventsToProcess != null) {
        for (ApplicationEvent earlyEvent : earlyEventsToProcess) {
           //3、派發之前步驟產生的事件;
            getApplicationEventMulticaster().multicastEvent(earlyEvent);
        }
    }
}
image

2.10 finishBeanFactoryInitialization(beanFactory);初始化所有剩下的單實例bean

在完成BeanFactory初始化之時,會初始化容器內所有單例非懶加載對象,供后續業務邏輯進行依賴注入等使用,具體實現在finishBeanFactoryInitialization(beanFactory)內部的最后一行代碼:

// 預實例化所有非懶加載單例Bean
beanFactory.preInstantiateSingletons();

具體的preInstantiateSingletons實現如下:

image

image

如上所示代碼:

beanNames = new ArrayList<String>(this.beanDefinitionNames);

  • 獲取容器內加載的所有BeanDefinition
    for (String beanName : beanNames)
  • 遍歷初始化所有非懶加載單例Bean

RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);

  • Bean定義公共的抽象類是AbstractBeanDefinition,普通的Bean在Spring加載Bean定義的時候,實例化出來的是GenericBeanDefinition
  • 而Spring上下文包括實例化所有Bean用的AbstractBeanDefinitionRootBeanDefinition
  • 這時候就使用getMergedLocalBeanDefinition方法做了一次轉化,將非RootBeanDefinition轉換為RootBeanDefinition以供后續操作。
  • 注意如果當前BeanDefinition存在父BeanDefinition,會基于父BeanDefinition生成一個RootBeanDefinition,然后再將調用OverrideFrom子BeanDefinition的相關屬性覆寫進去。

if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit())

  • 如果Bean不是抽象的,是單例的,不是懶加載的,則開始創建單例對象通過調用getBean(beanName)方法初始化

具體getBean函數實現如下所示:
[站外圖片上傳中...(image-a39a5e-1551843463104)]

進一步調用了如下方法,其中有參數:

image

image

image

final String beanName = transformedBeanName(name);

  • 如果是FactoryBean,會去掉Bean開頭的&符號;
  • 可能存在傳入別名且別名存在多重映射的情況,這里會返回最終的名字,如存在多層別名映射A->B->C->D,傳入D,最終會返回A

Object sharedInstance = getSingleton(beanName);

  • 根據beanName從緩存中獲取Bean ;從緩存中獲取BeanInstance,根據不同的情況這個Bean實例做處理,或直接返回,
  • 這里先嘗試從緩存中獲取,獲取不到再走后面創建的流程
  • 獲取到有兩種情況,一種是Bean創建完成存儲到最終的緩存中。
  • 另一種是未創建完成,但先預存到一個單獨的緩存中,這種是針對可能存在循環引用的情況的處理。

bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);

  • 這里主要處理實現了FactoryBean的情況,需要調用重寫的getObject()方法來獲取實際的Bean實例。真正的bean 返回處理

if (isPrototypeCurrentlyInCreation(beanName)) { throw new BeanCurrentlyInCreationException(beanName); }

  • 原型對象不允許循環創建,如果是原型對象則拋異常
  • 假設循環依賴的時候,如果我們已經開始在當前線程中創建此bean實例,但是還沒有創建完成,則失敗;
  • 例如此時是A依賴于B,但是B不依賴于A,B也沒有任何屬性依賴于A,則不存在循環依賴,那么無論B初始化,未初始化都不會有以下情況。但是如果B依賴于A,A在獲取依賴的Bean是激活創建B的方法,那么B創建過程中就會出現以下情況。就會出現循環依賴錯誤。如果A,B 是單例的并且A的構造函數不包含B,B的構造函數不包含A,spring還是可以通過提前暴露實例地址處理這種依賴,但是其它情況spring也無能為力了。

BeanFactory parentBeanFactory = getParentBeanFactory();

  • 獲取父bean工廠

if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
return parentBeanFactory.getBean()

  • 如果存在父bean工廠并且沒有配置該bean,則從父bean工廠創建

markBeanAsCreated(beanName);

  • 進行已創建標記

final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);

image
  • 根據名字獲取合并過的對應的RootBeanDefinition
  • 獲取緩存的BeanDefinition對象并合并其父類和本身的屬性。
  • 上面初始化得到的Bean的BeanDefinition用上
  • 轉換BeanDefinition

String[] dependsOn = mbd.getDependsOn();

  • 獲取依賴的Bean
  • 確保當前Bean依賴的相關Bean先完成初始化工作
  • depends-on標簽;depend-on用來表示一個Bean的實例化依靠另一個Bean先實例化

if (mbd.isSingleton()) {

  • 開始創建Bean實例了,如果是單例的,那么會創建一個單例的匿名工廠

else if (mbd.isPrototype()) {

  • 原型模式 ,則不需要創建單例的工廠
1.singleton模式通過getSingleton方法,這個里面創建對象時會先校驗緩存是 否已經存在該對象;
2.prototype模式直接創建對象,
3.其他類型的則可以通過自定義Scope來實現邏輯控制,
  設想一下如果把對象放到第三方緩存中則可在這邊自定義一個Scope。
  最終bean的構造委托給了createBean
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • 2.1 我們的理念是:讓別人為你服務 IoC是隨著近年來輕量級容器(Lightweight Container)的...
    好好學習Sun閱讀 2,733評論 0 11
  • 本來是準備看一看Spring源碼的。然后在知乎上看到來一個帖子,說有一群**自己連Spring官方文檔都沒有完全讀...
    此魚不得水閱讀 6,952評論 4 21
  • Spring容器高層視圖 Spring 啟動時讀取應用程序提供的Bean配置信息,并在Spring容器中生成一份相...
    Theriseof閱讀 2,838評論 1 24
  • 今天熬過去就一周啦~ 一日三餐 早 半個梨 半個芒果 一個麥片 一杯酸奶三個棗 一個雞蛋(怎么感覺我在增肥。。。)...
    木青就是我閱讀 310評論 0 0
  • 人生有那么多的細節 讓我們乎略 使諸多的可能 付諸東流。 人生有那么多的毫離 使成功漸行漸遠, 成為暮然回首。 別...
    泰康人壽詩人閱讀 304評論 5 3