Spring容器的建立刷新過程

Spring容器的建立刷新過程

以AnnotionConfigApplicationContext爲例,在new一個AnnotionConfigApplicationContext的時候,其構造函數內就會調用父類的refresh方法java

public AnnotationConfigApplicationContext(Class<?>... annotatedClasses) {
    this();
    register(annotatedClasses);
    refresh();// <-- 調用AbstractApplicationContext的refresh方法
}

因此呢,Spring容器的建立過程主要在這個refresh方法裏邊。spring

public void refresh() throws BeansException, IllegalStateException {
    synchronized (this.startupShutdownMonitor) {
        // 一、Prepare this context for refreshing.
        prepareRefresh();

        ///二、Tell the subclass to refresh the internal bean factory.
        ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

        ///三、Prepare the bean factory for use in this context.
        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();
        }
    }
}

我給源碼的每一步都加了序號(1~12),下面來詳細看看每一步都作了些什麼。緩存

一、prepareRefresh() 刷新前準備
  1. 設置一些狀態標記,如啓動時間startupDate,closed/active狀態app

  2. initPropertySources() 設置init屬性,此方法交給子類去實現函數

  3. getEnvironment().validateRequiredProperties()post

    若是無Environment,則new StandardEnvironment()ui

    再調用validateRequiredProperties() 校驗參數this

  4. earlyApplicationEvents= new LinkedHashSet ();保存容器中的一些早期的事件 代理

二、obtainFreshBeanFactory() 獲取BeanFactory
  1. refreshBeanFactory() 刷新BeanFactorycode

    GenericApplicationContext的構造方法中new了一個DefaultListableBeanFactory

    經過this.beanFactory.setSerializationId(getId());設置一個惟一的id

  2. getBeanFactory() 返回剛纔GenericApplicationContext建立的BeanFactory對象

三、prepareBeanFactory(beanFactory) BeanFactory的準備工做
  1. 設置BeanFactory的類加載器、表達式解析器【StandardBeanExpressionResolver】、ResourceEditorRegistrar

  2. 添加BeanPostProcessor【ApplicationContextAwareProcessor】

  3. 設置不須要自動裝配的接口

    包括【EnvironmentAware、EmbeddedValueResolverAware、ResourceLoaderAware、ApplicationEventPublisherAware、MessageSourceAware、ApplicationContextAware】

  4. 註冊能夠解析的自動裝配的接口

    包括【BeanFactory、ResourceLoader、ApplicationEventPublisher、ApplicationContext】

  5. 添加BeanPostProcessor【ApplicationListenerDetector】

  6. 添加AspectJ【類加載時織入LoadTimeWeaver】

  7. 給BeanFactory中註冊一些能用的組件

    1. environment【ConfigurableEnvironment】

    2. systemProperties【Map<String, Object>】

    3. systemEnvironment【Map<String, Object>】

四、postProcessBeanFactory(beanFactory) BeanFactory後置處理

子類經過重寫這個方法來在BeanFactory建立並預準備完成之後作進一步的設置

到這裏,BeanFactory的建立及後置處理工做就結束了

五、invokeBeanFactoryPostProcessors(beanFactory) 執行BeanFactory後置方法

BeanFactoryPostProcessors是BeanFactory的後置處理器,在BeanFactory標準初始化以後、所有bean信息都被加載,可是尚未被實例化的時候執行。

invokeBeanFactoryPostProcessors方法中,主要處理2種類型的接口:

BeanDefinitionRegistryPostProcessor 和 BeanFactoryPostProcessor

■先執行BeanDefinitionRegistryPostProcessor的方法,過程以下:

  1. 獲取全部實現了BeanDefinitionRegistryPostProcessor接口的class

    beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false)
  2. 先執行實現了PriorityOrdered優先級接口的BeanDefinitionRegistryPostProcessor

    postProcessor.postProcessBeanDefinitionRegistry(registry)
  3. 同理,再執行實現了Order順序接口的BeanDefinitionRegistryPostProcessor;最後執行其餘實現了BeanDefinitionRegistryPostProcessor的

Configuration類中經過@Import(ImportBeanDefinitionRegistrar)引入的類就是在這裏被調用registerBeanDefinitions方法的…【processor:ConfigurationClassPostProcessor】
java public void registerBeanDefinitions( AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry)

■再執行BeanFactoryPostProcessor的方法,過程以下:

  1. 獲取全部實現了BeanFactoryPostProcessor接口的class

    beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false)
  2. 先執行實現了PriorityOrdered優先級接口的BeanFactoryPostProcessor

    postProcessor.postProcessBeanFactory(beanFactory)
  3. 同理,再執行實現了Order順序接口的BeanFactoryPostProcessor;最後執行其餘實現了BeanDefinitionRegistryPostProcessor的

六、registerBeanPostProcessors(beanFactory) 註冊bean的後置處理器
  1. 獲取全部實現了BeanPostProcessor接口的class

    beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);
  2. 把獲取的類按照 是否實現了 PriorityOrdered、Ordered接口、及其餘 分紅3類

  3. 按照優先級依次調用

    beanFactory.addBeanPostProcessor(postProcessor);
  4. 最後註冊一個ApplicationListenerDetector

    beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext));

這個Detector的做用是:

在Bean建立完成後檢查是不是ApplicationListener,若是是則加到context中applicationContext.addApplicationListener((ApplicationListener<?>) bean)

七、initMessageSource() 初始化MessageSource組件

MessageSource組件主要用來實現國際化、消息解析處理。

在initMessageSource中,首先看容器中是否有id爲messageSource的,類型是MessageSource的組件。若是沒有則new DelegatingMessageSource() 放進去。

後面在處理國際化時,能夠注入MessageSource對象,而後使用以下代碼進行國際化

String getMessage(String code, Object[] args, Locale locale)
八、initApplicationEventMulticaster() 初始化事件多波器

在此方法中,首選從BeanFactory中獲取id爲「applicationEventMulticaster」的ApplicationEventMulticaster。若是沒有就new SimpleApplicationEventMulticaster(beanFactory)放進去。[多波器,有的也叫派發器]

九、onRefresh() 留給子類重寫
十、registerListeners() 註冊事件監聽器
  1. 從容器中拿到全部的ApplicationListener

  2. 將每一個監聽器添加到事件多波器中

    getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName)
  3. 處理前面步驟留下的earlyApplicationEvents,earlyApplicationEvents在步驟1.4中初始化爲空的LinkedHashSet

    getApplicationEventMulticaster().multicastEvent(earlyEvent)
十一、finishBeanFactoryInitialization(beanFactory) 初始化全部剩下的單實例bean

核心邏輯在beanFactory.preInstantiateSingletons()方法中。這裏面作的事情主要有:

  1. 循環編譯全部的beanNames,獲取RootBeanDefinition

  2. 若是bean 不是抽象的,是單實例的,是懶加載

  3. 判斷是否 是實現FactoryBean接口的Bean

    若是是,先作一些處理,再調getBean

    若是不是,則直接調用getBean(beanName)

  4. getBean(beanName) –> doGetBean(name, null, null, false)

    1. 先獲取緩存中保存的單實例Bean【singletonObjects.get(beanName)】。若是能獲取到說明這個Bean以前被建立過(全部建立過的單實例Bean都會被緩存在ConcurrentHashMap<String, Object>(256)中)

    2. 若是緩存中獲取不到,則開啓下面的建立流程

    3. 先將bean標記爲已建立 markBeanAsCreated(beanName)

    4. 獲取Bean的定義信息RootBeanDefinition

    5. 獲取當前Bean依賴的其餘Bean[mbd.getDependsOn()],若是有則調用getBean()把依賴的Bean先建立出來

    6. 開啓單實例Bean的建立流程 createBean(beanName, mbd, args)

      1. 準備重寫的方法

      2. 嘗試返回代理對象

        // Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
        Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
      3. 執行InstantiationAwareBeanPostProcessor

        先觸發:postProcessBeforeInstantiation();
        若是BeforeInstantiation有返回值,再接着執行postProcessAfterInitialization();

        若是resolveBeforeInstantiation返回的不爲null,則bean就建立好了

      4. 前面resolveBeforeInstantiation返回的不爲null,則返回該bean;爲null接着調Object beanInstance = doCreateBean(beanName, mbdToUse, args);建立Bean【step5】

  5. 建立doCreateBean(beanName, mbdToUse, args)

    1. 建立instanceWrapper = createBeanInstance(beanName, mbd, args)

      利用工廠方法 或 對象的構造器 建立出Bean實例

    2. 調用MergedBeanDefinitionPostProcessor的postProcessMergedBeanDefinition(mbd, beanType, beanName);

    3. 給bean屬性賦值 populateBean(beanName, mbd, instanceWrapper)

      1. 賦值前,拿到全部的InstantiationAwareBeanPostProcessor後置處理器,調用postProcessAfterInstantiation()

      2. 再拿到全部的InstantiationAwareBeanPostProcessor後置處理器,調用postProcessPropertyValues()

      3. 賦值 applyPropertyValues(beanName, mbd, bw, pvs);

        爲屬性利用setter方法等進行賦值

  6. 初始化bean,調用initializeBean(beanName, exposedObject, mbd)

    1. 執行xxxAware方法 invokeAwareMethods(beanName, bean),包括【BeanNameAware\BeanClassLoaderAware\BeanFactoryAware】

    2. 執行Bean後置處理器的before方法 applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName) 循環調用 beanProcessor.postProcessBeforeInitialization(result, beanName)

    3. 執行bean的初始化方法 invokeInitMethods(beanName, wrappedBean, mbd);

    4. 執行bean的後置處理器的after方法 applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName) 循環調用 beanProcessor.postProcessAfterInitialization(result, beanName)

      Spring的AOP註解實現原理:

      @EnableAspectJAutoProxy引入了繼承自AbstractAutoProxyCreator的AnnotationAwareAspectJAutoProxyCreator

      在AbstractAutoProxyCreator中實現了postProcessAfterInitialization方法,在方法內調用wrapIfNecessary(bean, beanName, cacheKey)方法建立代理對象返回出去,後續放入容器的就是這個代理對象

    5. 註冊bean的銷燬方法 registerDisposableBeanIfNecessary(beanName, bean, mbd);

  7. 將bean加入到singletonObjects中

  8. 全部bean建立完以後,判斷bean是不是SmartInitializingSingleton的實例。若是是,就執行afterSingletonsInstantiated()

十二、finishRefresh() 容器建立完成
  1. initLifecycleProcessor() 初始化和生命週期有關的後置處理器

    默認從容器中找是否有lifecycleProcessor的組件【LifecycleProcessor】;若是沒有new DefaultLifecycleProcessor();加入到容器;

  2. 執行onfresh方法

    getLifecycleProcessor().onRefresh()
  3. 發佈容器刷新完成事件

    publishEvent(new ContextRefreshedEvent(this))
  4. 調用LiveBeansView.registerApplicationContext(this)

相關文章
相關標籤/搜索