Spring 刷新應用上下文refreshContext

1.簡介

本篇文章是針對上篇文章啓動原理的補充,主要介紹Spring IOC容器初始化中刷新應用上下文操做。java

2.代碼解析

查看源碼發現refreshContext(context) --> refresh(context) --> ApplicationContext.refresh()
因此咱們這裏詳細說一下這個refresh()方法。
代碼以下:web

public void refresh() throws BeansException, IllegalStateException {
        synchronized (this.startupShutdownMonitor) {
            //第一步:容器刷新前的準備,設置上下文狀態,獲取屬性,驗證必要的屬性等
            prepareRefresh();
            
            //第二步:獲取新的beanFactory,銷燬原有beanFactory、爲每一個bean生成BeanDefinition等,注意此處是獲取新的,銷燬舊的,這就是刷新的意義(Spring容器裏經過BeanDefinition對象來表示Bean,BeanDefinition描述了Bean的配置信息。)
            ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
        
            //第三步:配置標準的beanFactory,設置ClassLoader,設置SpEL表達式解析器等
            prepareBeanFactory(beanFactory);
            try {
                //第四步:在全部的beanDenifition加載完成以後,bean實例化以前執行。好比在beanfactory加載完成全部的bean後,想修改其中某個bean的定義,或者對beanFactory作一些其餘的配置,就能夠在子類中對beanFactory進行後置處理。
                postProcessBeanFactory(beanFactory);

                //第五步:實例化並調用全部註冊的beanFactory後置處理器(實現接口BeanFactoryPostProcessor的bean) 
                invokeBeanFactoryPostProcessors(beanFactory);
         
               //第六步:實例化和註冊beanFactory中擴展了BeanPostProcessor的bean。
                //例如: AutowiredAnnotationBeanPostProcessor(處理被@Autowired註解修飾的bean並注入)
                //RequiredAnnotationBeanPostProcessor(處理被@Required註解修飾的方法)
                //CommonAnnotationBeanPostProcessor(處理@PreDestroy、@PostConstruct、@Resource等多個註解的做用)等。
                registerBeanPostProcessors(beanFactory);

                //第七步:初始化國際化工具類MessageSource
                initMessageSource();

                //第八步:初始化應用事件廣播器。這是觀察者模式的典型應用。咱們知道觀察者模式由主題Subject和Observer組成。廣播器至關於主題Subject,其包含多個監聽器。當主題發生變化時會通知全部的監聽器。初始化應用消息廣播器,並放入"ApplicationEventMulticaster" Bean中
                initApplicationEventMulticaster();

                //第九步:這個方法在AnnotationApplicationContex上下文中沒有實現,留給子類來初始化其餘的Bean,是個模板方法,在容器刷新的時候能夠自定義邏輯(子類本身去實現邏輯),不一樣的Spring容器作不一樣的事情
                onRefresh();

                //第十步:註冊監聽器,而且廣播early application events,也就是早期的事件
                registerListeners();

                //第十一步:初始化剩下的單例(非懶加載的單例類)(並invoke BeanPostProcessors)
                //實例化全部剩餘的(非懶加載)單例Bean。(也就是咱們本身定義的那些Bean)
                //好比invokeBeanFactoryPostProcessors方法中根據各類註解解析出來的類,在這個時候都會被初始化,掃描的@Bean之類的,
                //實例化的過程各類BeanPostProcessor開始起做用
                finishBeanFactoryInitialization(beanFactory);

                //第十二步:完成刷新過程,通知生命週期處理器lifecycleProcessor完成刷新過程,同時發出ContextRefreshEvent通知別人
                //refresh作完以後須要作的其餘事情
                //清除上下文資源緩存(如掃描中的ASM元數據)
                //初始化上下文的生命週期處理器,並刷新(找出Spring容器中實現了Lifecycle接口的bean並執行start()方法)。
                //發佈ContextRefreshedEvent事件告知對應的ApplicationListener進行響應的操做
                finishRefresh();
            }

            catch (BeansException ex) {
                if (logger.isWarnEnabled()) {
                    logger.warn("Exception encountered during context initialization - " +
                            "cancelling refresh attempt: " + ex);
                }
               //若是刷新失敗那麼就會將已經建立好的單例Bean銷燬掉
                destroyBeans();

                //重置context的活動狀態 告知是失敗的
                cancelRefresh(ex);

                //拋出異常
                throw ex;
            }

            finally {
                // 失敗與否,都會重置Spring內核的緩存。由於可能再也不須要metadata給單例Bean了。
                resetCommonCaches();
            }
        }
    }

2.1第一步:容器刷新前的準備

protected void prepareRefresh() {
        //記錄容器啓動時間,而後設立對應的標誌位
        this.startupDate = System.currentTimeMillis();
        this.closed.set(false);
        this.active.set(true);
        // 打印info日誌:開始刷新當前容器了
        if (logger.isInfoEnabled()) {
            logger.info("Refreshing " + this);
        }

        // 這是擴展方法,由子類去實現,能夠在驗證以前爲系統屬性設置一些值能夠在子類中實現此方法
        // 由於咱們這邊是AnnotationConfigApplicationContext,能夠看到無論父類仍是本身,都什麼都沒作,因此此處先忽略
        initPropertySources();

        //屬性文件驗證,確保須要的文件都已經放入環境中
        getEnvironment().validateRequiredProperties();

        //初始化容器,用於裝載早期的一些事件
        this.earlyApplicationEvents = new LinkedHashSet<>();
    }

2.2第二步:獲取新的beanFactory

obtainFreshBeanFactory()方法會解析全部Spring配置文件(一般咱們會放在 resources 目錄下),將全部 Spring 配置文件中的 bean 定義封裝成 BeanDefinition,加載到 BeanFactory中。常見的,若是解析到<context:component-scan base-package="" /> 註解時,會掃描 base-package 指定的目錄,將該目錄下使用指定註解(@Controller、@Service、@Component、@Repository)的 bean 定義也一樣封裝成 BeanDefinition,加載到 BeanFactory 中。spring

protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
        //初始化BeanFactory
        refreshBeanFactory();
        //返回初始化以後的BeanFactory
        ConfigurableListableBeanFactory beanFactory = getBeanFactory();
        if (logger.isDebugEnabled()) {
            logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory);
        }
        return beanFactory;
    }
protected final void refreshBeanFactory() throws BeansException {
        //判斷是否已經存在BeanFactory,存在則銷燬全部Beans,而且關閉BeanFactory
        if (hasBeanFactory()) {
            //銷燬全部的bean
            destroyBeans();
            //關閉並銷燬BeanFactory
            closeBeanFactory();
        }
        try {
           //建立具體的beanFactory,這裏建立的是DefaultListableBeanFactory,最重要的beanFactory spring註冊及加載bean就靠它
            DefaultListableBeanFactory beanFactory = createBeanFactory();
            beanFactory.setSerializationId(getId());
            //定製BeanFactory,包括是否容許覆蓋同名稱的不一樣定義的對象以及循環依賴
            customizeBeanFactory(beanFactory);
            //這個就是最重要的了,加載全部的Bean配置信息(屬於模版方法,由子類去實現加載的方式)
            loadBeanDefinitions(beanFactory);
            synchronized (this.beanFactoryMonitor) {
                this.beanFactory = beanFactory;
            }
        }
        catch (IOException ex) {
            throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
        }
    }
protected void customizeBeanFactory(DefaultListableBeanFactory beanFactory) {
        //allowBeanDefinitionOverriding屬性是指是否允對一個名字相同但definition不一樣進行從新註冊,默認是true。
        if (this.allowBeanDefinitionOverriding != null) {
            beanFactory.setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
        }
         //allowCircularReferences屬性是指是否容許Bean之間循環引用,默認是true.
        if (this.allowCircularReferences != null) {
            beanFactory.setAllowCircularReferences(this.allowCircularReferences);
        }
    }

實現loadBeanDefinitions()的子類有多種,如AbstractXmlApplicationContext類提供了基於XML的加載實現,AnnotationConfigWebApplicationContext類提供了在webapp的場景下基於註解配置的加載實現,XmlWebApplicationContext類提供了在webapp場景下基於xml配置的加載實現,XmlPortletApplicationContext提供了在portalet下基於xml配置的加載實現,GroovyWebApplicationContext類提供了基於groovy腳本配置的加載實現。
clipboard.pngapache

下面以AnnotationConfigWebApplicationContext#loadBeanDefinitions()方法爲例看下代碼。數組

protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) {
        //初始化這個腳手架 其實就是直接new出實例
       AnnotatedBeanDefinitionReader reader = getAnnotatedBeanDefinitionReader(beanFactory);
        ClassPathBeanDefinitionScanner scanner = getClassPathBeanDefinitionScanner(beanFactory);
        // 生成Bean的名稱的生成器,若是本身沒有setBeanNameGenerator(能夠自定義),這裏目前爲null
        BeanNameGenerator beanNameGenerator = getBeanNameGenerator();
        if (beanNameGenerator != null) {
            reader.setBeanNameGenerator(beanNameGenerator);
            scanner.setBeanNameGenerator(beanNameGenerator);
            //若咱們註冊了beanName生成器,那麼就會註冊進容器裏面
            beanFactory.registerSingleton(AnnotationConfigUtils.CONFIGURATION_BEAN_NAME_GENERATOR, beanNameGenerator);
        }
        
        //這是給reader和scanner註冊scope的解析器  此處爲null
        ScopeMetadataResolver scopeMetadataResolver = getScopeMetadataResolver();
        if (scopeMetadataResolver != null) {
            reader.setScopeMetadataResolver(scopeMetadataResolver);
            scanner.setScopeMetadataResolver(scopeMetadataResolver);
        }

        //咱們能夠本身指定annotatedClasses 配置文件,同時也能夠交給下面掃描
        if (!this.annotatedClasses.isEmpty()) {
            // 這裏會把全部的配置文件輸出=======info日誌  請注意觀察控制檯
            if (logger.isDebugEnabled()) {
                logger.debug("Registering annotated classes: [" +
                        StringUtils.collectionToCommaDelimitedString(this.annotatedClasses) + "]");
            }
            // 如果指明的Bean,就交給reader去處理
            reader.register(ClassUtils.toClassArray(this.annotatedClasses));
        }

        // 也能夠是包掃描的方式,掃描配置文件的Bean
        if (!this.basePackages.isEmpty()) {
            if (logger.isDebugEnabled()) {
                logger.debug("Scanning base packages: [" +
                        StringUtils.collectionToCommaDelimitedString(this.basePackages) + "]");
            }
            scanner.scan(StringUtils.toStringArray(this.basePackages));
        }

        // 此處的意思是,也能夠以全類名的形式註冊。好比能夠調用setConfigLocations設置(這在xml配置中使用較多)  能夠是全類名,也能夠是包路徑
        String[] configLocations = getConfigLocations();
        if (configLocations != null) {
            for (String configLocation : configLocations) {
                try {
                    Class<?> clazz = ClassUtils.forName(configLocation, getClassLoader());
                    if (logger.isTraceEnabled()) {
                        logger.trace("Registering [" + configLocation + "]");
                    }
                    reader.register(clazz);
                }
                catch (ClassNotFoundException ex) {
                    if (logger.isTraceEnabled()) {
                        logger.trace("Could not load class for config location [" + configLocation +
                                "] - trying package scan. " + ex);
                    }
                    int count = scanner.scan(configLocation);
                   // 發現不是全類名,那就看成包掃描
                    if (count == 0 && logger.isDebugEnabled()) {
                        logger.debug("No annotated classes found for specified class/package [" + configLocation + "]");
                    }
                }
            }
        }
    }

該方法主要是解析咱們項目配置的 application.xml、xxx.xml 定義的import、bean、resource、profile、、、、、。或掃描註解 將其屬性封裝到BeanDefinition 對象中。緩存

上面提到的 「加載到 BeanFactory 中」 的內容主要指的是添加到如下3個緩存:
beanDefinitionNames緩存:全部被加載到 BeanFactory 中的 bean 的 beanName 集合。
beanDefinitionMap緩存:全部被加載到 BeanFactory 中的 bean 的 beanName 和 BeanDefinition 映射( Map<String, BeanDefinition>,beanName--key和beanDefinition--value)。
aliasMap緩存:全部被加載到 BeanFactory 中的 bean 的 beanName 和別名映射。tomcat

如今BeanFactory已經建立完成了,而且Config配置文件的Bean定義已經註冊完成了(備註:其它單例Bean是尚未解析的),下面的步驟大都把BeanFactory傳進去了,都是基於此Bean工廠的操做。session

2.3第三步:配置標準的beanFactory

至此,spring已經完成了對配置的解析,開始ApplicationContext功能上的擴展。app

protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
        //設置beanFactory的classLoader爲當前context的classLoader
        beanFactory.setBeanClassLoader(getClassLoader());
        //設置EL表達式解析器(Bean初始化完成後填充屬性時會用到)
        beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
        //設置屬性註冊解析器PropertyEditor 這個主要是對bean的屬性等設置管理的一個工具
        beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));

        // 將當前的ApplicationContext對象交給ApplicationContextAwareProcessor類來處理,從而在Aware接口實現類中的注入applicationContext等等
        // 添加了一個處理aware相關接口的beanPostProcessor擴展,主要是使用beanPostProcessor的postProcessBeforeInitialization()前置處理方法實現aware相關接口的功能
        // 相似的還有下面的ResourceLoaderAware、ServletContextAware等等等等
        beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
        
        //設置幾個忽略自動裝配的接口( 默認只有BeanFactoryAware被忽略,因此其它的須要自行設置)
        beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
        beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
        beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
        beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
        beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
        beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);

        
        // 設置幾個"自動裝配"規則======以下:
        // 若是是BeanFactory的類,就註冊beanFactory
        //  若是是ResourceLoader、ApplicationEventPublisher、ApplicationContext等等就注入當前對象this(applicationContext對象)
        
        // 此處registerResolvableDependency()方法注意:它會把他們加入到DefaultListableBeanFactory的resolvableDependencies字段裏面緩存這,供後面處理依賴注入的時候使用 DefaultListableBeanFactory#resolveDependency處理依賴關係
        // 這也是爲何咱們能夠經過依賴注入的方式,直接注入這幾個對象好比ApplicationContext能夠直接依賴注入
        // 可是須要注意的是:這些Bean,Spring的IOC容器裏實際上是沒有的。beanFactory.getBeanDefinitionNames()和beanFactory.getSingletonNames()都是找不到他們的,因此特別須要理解這一點
        // 至於容器中沒有,可是咱們仍是能夠@Autowired直接注入的有哪些,請看下圖
        beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
        beanFactory.registerResolvableDependency(ResourceLoader.class, this);
        beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
        beanFactory.registerResolvableDependency(ApplicationContext.class, this);

        // 註冊這個Bean的後置處理器:在Bean初始化後檢查是否實現了ApplicationListener接口
        // 是則加入當前的applicationContext的applicationListeners列表 這樣後面廣播事件也就方便了
        beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));

         // 檢查容器中是否包含名稱爲loadTimeWeaver的bean,其實是增長Aspectj的支持
        // AspectJ採用編譯期織入、類加載期織入兩種方式進行切面的織入
        // 類加載期織入簡稱爲LTW(Load Time Weaving),經過特殊的類加載器來代理JVM默認的類加
        if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
            // 添加BEAN後置處理器:LoadTimeWeaverAwareProcessor
            // 在BEAN初始化以前檢查BEAN是否實現了LoadTimeWeaverAware接口,
            // 若是是,則進行加載時織入,即靜態代理。
            beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));

            beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
        }

        // 注入一些系統環境的bean,好比environment、systemProperties、SystemEnvironment等
        if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {
            beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());
        }
        if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {
            beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());
        }
        if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {
            beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());
        }
    }

附:IOC容器中沒有Bean,可是咱們仍是能夠依賴注入的Bean以下(resolvableDependencies):
b1be60253114f171554d6c6e71142e2f.pngwebapp

主要擴展:
1. 增長對SPEL語言的支持;
2. 增長對屬性編輯器的支持,這些PropertyEditors在這裏只是註冊,使用的時候是將bean包裝成BeanWrapper,包裝後的BeanWrapper的就包含了全部的這些PropertyEditors,以便後期給bean設置屬性的時候使用;
3. 增長對一些內置類(實際上就是前置處理器),好比Aware接口的信息注入;
4. 設置依賴功能可忽略的接口;
5. 註冊一些固定的bean,這些都是特殊的依賴解析,好比當註冊了BeanFactory.class的依賴解析以後,當bean的屬性注入的時候,一旦檢測到屬性爲BeanFactory類型便會將beanFactory的實例注入進去;
6. 增長對AspectJ的支持;
7. 將相關環境變量及屬性以單例模式註冊。

2.4第四步:postProcessBeanFactory方法

到這裏beanFactory都準備好了,子類能夠本身去實現本身的邏輯。因此postProcessBeanFactory這個模版方法用於子類對beanFactory進行後置處理。好比一些web的ApplicationContext,就實現了本身的邏輯,作一些本身的web相關的事情。此處咱們看下AbstractRefreshableWebApplicationContext#postProcessBeanFactory方法:

protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
        //註冊ServletContextAwareProcessor 這樣任意Bean均可以很方便的獲取到ServletContext了  同時忽略另外兩個,由於ServletContextAwareProcessor 都把事情都作了
        beanFactory.addBeanPostProcessor(new ServletContextAwareProcessor(this.servletContext, this.servletConfig));
        beanFactory.ignoreDependencyInterface(ServletContextAware.class);
        beanFactory.ignoreDependencyInterface(ServletConfigAware.class);
        //註冊web環境,包括request、session、golableSession、application
        WebApplicationContextUtils.registerWebApplicationScopes(beanFactory, this.servletContext);
        //註冊servletContext、contextParamters、contextAttributes  、servletConfig單例bean
       WebApplicationContextUtils.registerEnvironmentBeans(beanFactory, this.servletContext, this.servletConfig);
    }

2.5第五步:激活各類BeanFactory處理器

invokeBeanFactoryPostProcessors執行BeanFactory後置處理器,前提是你已經在容器中註冊過此處理器了。這個接口跟BeanPostProcessor相似,能夠對bean的定義(配置元數據)進行處理,做用範圍是容器級的,只對本身的容器的bean進行處理。

protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
// 1.getBeanFactoryPostProcessors(): 拿到當前應用上下文beanFactoryPostProcessors變量中的值
    // 2.invokeBeanFactoryPostProcessors: 實例化並調用全部已註冊的BeanFactoryPostProcessor    PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());

        // 這裏就是定製:若是loadTimeWeaver這個Bean存在,那麼就會配置上運行時織入的處理器LoadTimeWeaverAwareProcessor
        if (beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
            beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
            beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
        }
    }

拿到當前應用上下文 beanFactoryPostProcessors 變量中的值.

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

它不是返回Spring容器裏面的Processors,而是你本身的註冊的(你本身手動set的),也就是說咱們本身手動調用set方法添加進去,就可以執行。並不須要本身配置@Bean或者在xml裏配置,那麼重點就在於PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors:

public static void invokeBeanFactoryPostProcessors(
            ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {
        // 這個doc說明很清楚:無論怎麼樣,先執行BeanDefinitionRegistryPostProcessors 
        // 須要注意的是BeanDefinitionRegistryPostProcessors 爲 BeanFactoryPostProcessor 的子接口 它新增了方法:void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry)
        // BeanFactoryPostProcessor 的方法爲;void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;
        // 因此BeanDefinitionRegistryPostProcessors,咱們介入並改變Bean的一些定義信息
        Set<String> processedBeans = new HashSet<>();
        // 1.判斷beanFactory是否爲BeanDefinitionRegistry,beanFactory爲DefaultListableBeanFactory,
    // 而DefaultListableBeanFactory實現了BeanDefinitionRegistry接口,所以這邊爲true
    
        //1.只有此beanFactory是BeanDefinitionRegistry 才能執行BeanDefinitionRegistryPostProcessor,才能修改Bean的定義
        (beanFactory爲DefaultListableBeanFactory,而DefaultListableBeanFactory實現了BeanDefinitionRegistry接口,所以這邊爲true)
        if (beanFactory instanceof BeanDefinitionRegistry) {
            BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
            // 用於存放普通的BeanFactoryPostProcessor
            List<BeanFactoryPostProcessor> regularPostProcessors = new LinkedList<>();
            // 用於存放BeanDefinitionRegistryPostProcessor
            List<BeanDefinitionRegistryPostProcessor> registryProcessors = new LinkedList<>();
            都是LinkedList,因此執行順序和set進去的順序是保持同樣的
        // 2.首先處理入參中的beanFactoryPostProcessors
        // 遍歷全部的beanFactoryPostProcessors, 將BeanDefinitionRegistryPostProcessor和普通BeanFactoryPostProcessor區分開
            for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
                if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
                // 2.1 若是是BeanDefinitionRegistryPostProcessor
                    BeanDefinitionRegistryPostProcessor registryProcessor =
                            (BeanDefinitionRegistryPostProcessor) postProcessor;
                
                // 2.1.1 直接執行BeanDefinitionRegistryPostProcessor接口的postProcessBeanDefinitionRegistry方法    registryProcessor.postProcessBeanDefinitionRegistry(registry);
                // 2.1.2 添加到registryProcessors(用於最後執行postProcessBeanFactory方法)    registryProcessors.add(registryProcessor);
                }
                else {
                    // 2.2 不然,只是普通的BeanFactoryPostProcessor
                // 2.2.1 添加到regularPostProcessors(用於最後執行postProcessBeanFactory方法)regularPostProcessors.add(postProcessor);
                }
            }

             // 用於保存本次要執行的BeanDefinitionRegistryPostProcessor
            List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();

            // 3.調用全部實現PriorityOrdered接口的BeanDefinitionRegistryPostProcessor實現類
        // 3.1 找出全部實現BeanDefinitionRegistryPostProcessor接口的Bean的beanName
            String[] postProcessorNames =
                    beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
                    // 3.2 遍歷postProcessorNames
            for (String ppName : postProcessorNames) {
                // 3.3 校驗是否實現了PriorityOrdered接口
                if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
                    // 3.4 獲取ppName對應的bean實例, 添加到currentRegistryProcessors中,
                // beanFactory.getBean: 這邊getBean方法會觸發建立ppName對應的bean對象, 目前暫不深刻解析currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
                // 3.5 將要被執行的加入processedBeans,避免後續重複執行
                    processedBeans.add(ppName);
                }
            }
            // 3.6 進行排序(根據是否實現PriorityOrdered、Ordered接口和order值來排序)
            sortPostProcessors(currentRegistryProcessors, beanFactory);
            // 3.7 添加到registryProcessors(用於最後執行postProcessBeanFactory方法)
            registryProcessors.addAll(currentRegistryProcessors);
            // 3.8 遍歷currentRegistryProcessors, 執行postProcessBeanDefinitionRegistry方法invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
            // 3.9 執行完畢後, 清空currentRegistryProcessors
            currentRegistryProcessors.clear();

            // 4.調用全部實現了Ordered接口的BeanDefinitionRegistryPostProcessor實現類(過程跟上面的步驟3基本同樣)
        // 4.1 找出全部實現BeanDefinitionRegistryPostProcessor接口的類, 這邊重複查找是由於執行完上面的BeanDefinitionRegistryPostProcessor,
        // 可能會新增了其餘的BeanDefinitionRegistryPostProcessor, 所以須要從新查找

            postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
            for (String ppName : postProcessorNames) {
                // 校驗是否實現了Ordered接口,而且還未執行過
                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);
            // 4.2 遍歷currentRegistryProcessors, 執行postProcessBeanDefinitionRegistry方法invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
            currentRegistryProcessors.clear();

            // 5.最後, 調用全部剩下的BeanDefinitionRegistryPostProcessors
            boolean reiterate = true;
            while (reiterate) {
                reiterate = false;
                // 5.1 找出全部實現BeanDefinitionRegistryPostProcessor接口的類
                postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
                for (String ppName : postProcessorNames) {                  // 5.2 跳過已經執行過的
                    if (!processedBeans.contains(ppName)) {
                        currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
                        processedBeans.add(ppName);
                        // 5.3 若是有BeanDefinitionRegistryPostProcessor被執行, 則有可能會產生新的BeanDefinitionRegistryPostProcessor,
                    // 所以這邊將reiterate賦值爲true, 表明須要再循環查找一次
                        reiterate = true;
                    }
                }
                sortPostProcessors(currentRegistryProcessors, beanFactory);
                registryProcessors.addAll(currentRegistryProcessors);
                // 5.4 遍歷currentRegistryProcessors, 執行postProcessBeanDefinitionRegistry方法invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
                currentRegistryProcessors.clear();
            }

            
        // 6.調用全部BeanDefinitionRegistryPostProcessor的postProcessBeanFactory方法(BeanDefinitionRegistryPostProcessor繼承自BeanFactoryPostProcessor)
        
invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
            // 7.最後, 調用入參beanFactoryPostProcessors中的普通BeanFactoryPostProcessor的postProcessBeanFactory方法
            invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
        }

        else {
            // Invoke factory processors registered with the context instance.
            invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);
        }

// 到這裏 , 入參beanFactoryPostProcessors和容器中的全部BeanDefinitionRegistryPostProcessor已經所有處理完畢,
    // 下面開始處理容器中的全部BeanFactoryPostProcessor
        
        
    // 8.找出全部實現BeanFactoryPostProcessor接口的類
        String[] postProcessorNames =
                beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);

        // 用於存放實現了PriorityOrdered接口的BeanFactoryPostProcessor
        List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
        // 用於存放實現了Ordered接口的BeanFactoryPostProcessor的beanName
        List<String> orderedPostProcessorNames = new ArrayList<>();
        // 用於存放普通BeanFactoryPostProcessor的beanName
        List<String> nonOrderedPostProcessorNames = new ArrayList<>();
        // 8.1 遍歷postProcessorNames, 將BeanFactoryPostProcessor按實現PriorityOrdered、實現Ordered接口、普通三種區分開
        for (String ppName : postProcessorNames) {
        // 8.2 跳過已經執行過的
            if (processedBeans.contains(ppName)) {
                // skip - already processed in first phase above
            }
            else if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
                
            // 8.3 添加實現了PriorityOrdered接口的BeanFactoryPostProcessor               priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));
            }
            else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
            // 8.4 添加實現了Ordered接口的BeanFactoryPostProcessor的beanName

                orderedPostProcessorNames.add(ppName);
            }
            else {
            // 8.5 添加剩下的普通BeanFactoryPostProcessor的beanName
                nonOrderedPostProcessorNames.add(ppName);
            }
        }

        // 9.調用全部實現PriorityOrdered接口的BeanFactoryPostProcessor
    // 9.1 對priorityOrderedPostProcessors排序
        sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
        // 9.2 遍歷priorityOrderedPostProcessors, 執行postProcessBeanFactory方法
        invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);

        // 10.調用全部實現Ordered接口的BeanFactoryPostProcessor
        List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<>();
        for (String postProcessorName : orderedPostProcessorNames) {
            // 10.1 獲取postProcessorName對應的bean實例, 添加到orderedPostProcessors, 準備執行
            orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
        }
        // 10.2 對orderedPostProcessors排序
        sortPostProcessors(orderedPostProcessors, beanFactory);
        // 10.3 遍歷orderedPostProcessors, 執行postProcessBeanFactory方法
        invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);

        // 11.調用全部剩下的BeanFactoryPostProcessor
        List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<>();
        for (String postProcessorName : nonOrderedPostProcessorNames) {
            // 11.1 獲取postProcessorName對應的bean實例, 添加到nonOrderedPostProcessors, 準備執行
            nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
        }
        // 11.2 遍歷nonOrderedPostProcessors, 執行postProcessBeanFactory方法
        invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);

        / 12.清除元數據緩存(mergedBeanDefinitions、allBeanNamesByType、singletonBeanNamesByType),
    // 由於後處理器可能已經修改了原始元數據,例如, 替換值中的佔位符...
        beanFactory.clearMetadataCache();
    }

invokeBeanFactoryPostProcessors(beanFactory)這一步主要作了:

  • 執行了BeanDefinitionRegistryPostProcessor(此處只有ConfigurationClassPostProcessor)
  • 執行了BeanFactoryPostProcessor
  • 完成了@Configuration配置文件的解析,而且把掃描到的、配置的Bean定義信息都加載進容器裏
  • Full模式下,完成了對@Configuration配置文件的增強,使得管理Bean依賴關係更加的方便了

到這裏Bean工廠徹底準備好了,而且也註冊好了全部的Bean的定義信息(此時Bean還並無建立)。也完成了對配置文件的解析,能夠說Spring IOC容器的大部分準備工做已經完成了,接下來就是對Bean的一些初始化、操做

2.6第六步:註冊BeanPostProcessors

略。。。

2.7第七步:爲上下文初始化Message源,即不一樣語言的消息體,國際化處理

略。。。

2.8第八步:initApplicationEventMulticaster

略。。。

2.9第九步:onRefresh()

在接觸SpringBoot以前咱們的web項目都是須要部署到web服務容器上,如tomcat、weblogic、JBoss等,而後啓動web容器真正運行咱們的系統。

SpringBoot給咱們帶來了一個全新的開發體驗,咱們能夠把web程序打成jar包,直接啓動,這得益於SpringBoot內置了容器,能夠直接啓動,本文將以Tomcat爲例,來看看SpringBoot是如何啓動Tomcat的,同時也將展開學習下Tomcat的源碼,瞭解Tomcat的設計。

啓動Tomcat是在「刷新上下文」操做中;Tomcat的啓動主要是初始化2個核心組件,鏈接器(Connector)和容器(Container),一個Tomcat實例就是一個Server,一個Server包含多個Service,也就是多個應用程序,每一個Service包含多個鏈接器(Connetor)和一個容器(Container),而容器下又有多個子容器,按照父子關係分別爲:Engine,Host,Context,Wrapper,其中除了Engine外,其他的容器都是能夠有多個。

在onReFresh建立內置tomcat,在finishRefresh啓動tomcat

tomcat的編碼有點意思 咱們獲取任何一個容器的時候,在他內部都會包含獲取其父容器的方法

onRefresh()方法是調用其子類的實現,根據咱們上文的分析,咱們這裏的子類是ServletWebServerApplicationContext。
clipboard.png

//類:ServletWebServerApplicationContext
protected void onRefresh() {
    super.onRefresh();
    try {
      createWebServer();
    }
    catch (Throwable ex) {
      throw new ApplicationContextException("Unable to start web server", ex);
    }
  }
  
private void createWebServer() {
    WebServer webServer = this.webServer;
    ServletContext servletContext = getServletContext();
    //若是webServer 和servletContext 都爲空
    if (webServer == null && servletContext == null) {
    //經過spring去加載ServletWebServerFactory
      ServletWebServerFactory factory = getWebServerFactory();
      //建立webServer,這邊getSelfInitializer裏面就是咱們spring容器
      this.webServer = factory.getWebServer(getSelfInitializer());
    }
    else if (servletContext != null) {
      try {
          //若是servletContext 不爲空,調用ServletContextInitializer數組去啓動該容器,
          //即給改servletContext配置servlet,filters,listeners context-params 和attribute
        getSelfInitializer().onStartup(servletContext);
      }
      catch (ServletException ex) {
        throw new ApplicationContextException("Cannot initialize servlet context", ex);
      }
    }
    //把咱們建立好的額webServer好servletcontext,
    // 更新到ConfigurableWebEnvironment中
    // 前提是自己ConfigurableWebEnvironment就有這兩個屬性
    initPropertySources();
  }

到這裏,createWebServer()就是啓動web服務,可是尚未真正啓動Tomcat,既然webServer是經過ServletWebServerFactory來獲取的,咱們就來看看這個工廠的真面目。

clipboard.png
根據上圖咱們發現,工廠類是一個接口,各個具體服務的實現是由各個子類來實現的,因此咱們就去看看TomcatServletWebServerFactory.getWebServer()的實現。

建立webServer的過程,initializers就是spring的容器
@Override
  public WebServer getWebServer(ServletContextInitializer... initializers) {
    //建立tomcat
    Tomcat tomcat = new Tomcat();
    //建立一個臨時目錄個給當前webServer,並註冊了一個鉤子在程序退出的時候刪除文件夾
    File baseDir = (this.baseDirectory != null) ? this.baseDirectory : createTempDir("tomcat");
    //設置tomcat的baseDir,baseDir是給臨時文件使用的,
    //應該是第一個被調用的方法,若是該方法沒被調用,
    // 咱們默認調用系統屬性system properties - catalina.base, catalina.home
    //或者[user.dir]/tomcat.$PORT
    tomcat.setBaseDir(baseDir.getAbsolutePath());
    //根據protocol(默認是Http11NioProtocol)建立connector,
    // 這邊的邏輯是先看下是不是http協議,而後再看看是不是AJP協議,
    // 若是都不是直接塞入協議的名字,而後下一步根據協議的名字調用class.forName獲得協議類,
    // 而後經過org.apache.catalina.STRICT_SERVLET_COMPLIANCE屬性設置整個tomcat的編碼是ISO_8859_1仍是UTF-8
    Connector connector = new Connector(this.protocol);
    //給第一個service添加connector,這其中會初始化server(StandardServer)(server會初始化baseDir,設置初始化監聽關閉端口爲-1,這樣就不會被從端口關閉,建立標準的service(StandardServer))而後綁定二者
addConnector:尋找現有的connector數組,將connector添加進去並把connector和service互相綁定,而後啓動該connector
    tomcat.getService().addConnector(connector);
    //設置咱們自定義的端口號,添加server,bindOnInit屬性,添加咱們的協議,添加urlEncoding,設置ssl,compression
    customizeConnector(connector);
    //tomcat自己設置connector
    tomcat.setConnector(connector);
    //關閉自動部署
    tomcat.getHost().setAutoDeploy(false);
    //設置backgroundProcessorDelay機制,若是backgroundProcessorDelay爲正值,那麼子容器的一些任務會有後臺線程幫忙處理,爲負值,則由當前容器一併處理。這些任務都是週期性的好比例如從新加載等。
爲engine配置上Valve,設置container
    configureEngine(tomcat.getEngine());
    //給這個service添加額外的connector,從這能夠看出connector和service的關係是多對一 container和service是1對1
    for (Connector additionalConnector : this.additionalTomcatConnectors) {
      tomcat.getService().addConnector(additionalConnector);
    }
    //準備一個context給engine,這裏咱們設置TomcatEmbeddedContext,這個是spring本身寫的,而後配置好
這個context的一些屬性
    prepareContext(tomcat.getHost(), initializers);
    //啓動tomcat(即tomcat的容器被啓動,可是connector沒有啓動)
    return getTomcatWebServer(tomcat);
  }

根據上面的代碼,咱們發現其主要作了兩件事情,第一件事就是把Connnctor(咱們稱之爲鏈接器)對象添加到Tomcat中,第二件事就是configureEngine,這鏈接器咱們勉強能理解(不理解後面會述說),那這個Engine是什麼呢?咱們查看tomcat.getEngine()的源碼:

public Engine getEngine() {
        Service service = getServer().findServices()[0];
        if (service.getContainer() != null) {
            return service.getContainer();
        }
        Engine engine = new StandardEngine();
        engine.setName( "Tomcat" );
        engine.setDefaultHost(hostname);
        engine.setRealm(createDefaultRealm());
        service.setContainer(engine);
        return engine;
    }

根據上面的源碼,咱們發現,原來這個Engine是容器,咱們繼續跟蹤源碼,找到Container接口。

clipboard.png

上圖中,咱們看到了4個子接口,分別是Engine,Host,Context,Wrapper。咱們從繼承關係上能夠知道他們都是容器,Engine是最高級別的容器,其子容器是Host,Host的子容器是Context,Wrapper是Context的子容器,因此這4個容器的關係就是父子關係,也就是Engine>Host>Context>Wrapper。咱們再看看Tomcat類的源碼:

//部分源碼,其他部分省略。
public class Tomcat {
//設置鏈接器
     public void setConnector(Connector connector) {
        Service service = getService();
        boolean found = false;
        for (Connector serviceConnector : service.findConnectors()) {
            if (connector == serviceConnector) {
                found = true;
            }
        }
        if (!found) {
            service.addConnector(connector);
        }
    }
    //獲取service
       public Service getService() {
        return getServer().findServices()[0];
    }
    //設置Host容器
     public void setHost(Host host) {
        Engine engine = getEngine();
        boolean found = false;
        for (Container engineHost : engine.findChildren()) {
            if (engineHost == host) {
                found = true;
            }
        }
        if (!found) {
            engine.addChild(host);
        }
    }
    //獲取Engine容器
     public Engine getEngine() {
        Service service = getServer().findServices()[0];
        if (service.getContainer() != null) {
            return service.getContainer();
        }
        Engine engine = new StandardEngine();
        engine.setName( "Tomcat" );
        engine.setDefaultHost(hostname);
        engine.setRealm(createDefaultRealm());
        service.setContainer(engine);
        return engine;
    }
    //獲取server
       public Server getServer() {

        if (server != null) {
            return server;
        }

        System.setProperty("catalina.useNaming", "false");

        server = new StandardServer();

        initBaseDir();

        // Set configuration source
        ConfigFileLoader.setSource(new CatalinaBaseConfigurationSource(new File(basedir), null));

        server.setPort( -1 );

        Service service = new StandardService();
        service.setName("Tomcat");
        server.addService(service);
        return server;
    }
    
    //添加Context容器
      public Context addContext(Host host, String contextPath, String contextName,
            String dir) {
        silence(host, contextName);
        Context ctx = createContext(host, contextPath);
        ctx.setName(contextName);
        ctx.setPath(contextPath);
        ctx.setDocBase(dir);
        ctx.addLifecycleListener(new FixContextListener());

        if (host == null) {
            getHost().addChild(ctx);
        } else {
            host.addChild(ctx);
        }
        
    //添加Wrapper容器
         public static Wrapper addServlet(Context ctx,
                                      String servletName,
                                      Servlet servlet) {
        // will do class for name and set init params
        Wrapper sw = new ExistingStandardWrapper(servlet);
        sw.setName(servletName);
        ctx.addChild(sw);

        return sw;
    }
    
}

閱讀Tomcat的getServer()咱們能夠知道,Tomcat的最頂層是Server,Server就是Tomcat的實例,一個Tomcat一個Server;經過getEngine()咱們能夠了解到Server下面是Service,並且是多個,一個Service表明咱們部署的一個應用,並且咱們還能夠知道,Engine容器,一個service只有一個;根據父子關係,咱們看setHost()源碼能夠知道,host容器有多個;同理,咱們發現addContext()源碼下,Context也是多個;addServlet()代表Wrapper容器也是多個,並且這段代碼也暗示了,其實Wrapper和Servlet是一層意思。另外咱們根據setConnector源碼能夠知道,鏈接器(Connector)是設置在service下的,並且是能夠設置多個鏈接器(Connector)。

根據上面分析,咱們能夠小結下:Tomcat主要包含了2個核心組件,鏈接器(Connector)和容器(Container),用圖表示以下:

clipboard.png

一個Tomcat是一個Server,一個Server下有多個service,也就是咱們部署的多個應用,一個應用下有多個鏈接器(Connector)和一個容器(Container),容器下有多個子容器,關係用圖表示以下:

clipboard.png

Engine下有多個Host子容器,Host下有多個Context子容器,Context下有多個Wrapper子容器。

2.10第十步:registerListeners

在全部註冊的Bean中查找Listenter bean,註冊到消息廣播器中。

protected void registerListeners() {
        // 首先註冊靜態註冊的監聽器(代碼註冊的)
        for (ApplicationListener<?> listener : getApplicationListeners()) {
            getApplicationEventMulticaster().addApplicationListener(listener);
        }

        // 獲取容器中全部配置的listener並註冊
        String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
        for (String listenerBeanName : listenerBeanNames) {
            getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
        }

        // 對earlyApplicationEvents這些事件進行廣播,實際上就是遍歷全部的listener,找到能夠處理event的listener處理
        Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;
        this.earlyApplicationEvents = null;
        if (earlyEventsToProcess != null) {
            for (ApplicationEvent earlyEvent : earlyEventsToProcess) {
                getApplicationEventMulticaster().multicastEvent(earlyEvent);
            }
        }
    }

2.11第十一步:finishBeanFactoryInitialization

初始化剩下的非惰性單例,若是某個單例依賴了惰性的單例,那麼這個惰性的單例也會被初始化,這個很好理解吧。

protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
        // 初始化ConversionService,跟PropertyEditor相似
        if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) &&
                beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {
            beanFactory.setConversionService(
                    beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));
        }

        //則註冊默認的嵌入值解析器
    //例如PropertyPlaceholderConfigurer bean)以前註冊過:
    //主要用於註解屬性值的解析。
        if (!beanFactory.hasEmbeddedValueResolver()) {
            beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal));
        }

        //單例bean初始化以前首先初始化LoadTimeWeaverAware,以支持aop,AspectJ
        String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
        for (String weaverAwareName : weaverAwareNames) {
            getBean(weaverAwareName);
        }

        // Stop using the temporary ClassLoader for type matching.
        beanFactory.setTempClassLoader(null);

        //凍結bean定義(BeanDefinition),表示全部的bean定義進不被修改或進行進一步處理
        beanFactory.freezeConfiguration();

        //初始化非惰性單例,實際上就是遍歷全部的beanName,而後一一調用getBean()
        beanFactory.preInstantiateSingletons();
    }

2.12第十二步:finishRefresh

protected void finishRefresh() {
        //清除上下文級別(context-level)的資源緩存,好比由scanning產生的ASM元數據
        clearResourceCaches();

        //初始化LifecycleProcessor
        initLifecycleProcessor();

         //使用LifecycleProcessor來啓動Lifecycle子類
        getLifecycleProcessor().onRefresh();

        //上下文刷新完成,發佈事件
        publishEvent(new ContextRefreshedEvent(this));

        // Participate in LiveBeansView MBean, if active.
        LiveBeansView.registerApplicationContext(this);
    }

初始化LifecycleProcessor的時候,跟初始化MessageResource同樣,沒有自定義的就是用默認的DefaultLifecycleProcessor。

getLifecycleProcessor().onRefresh()會使用咱們註冊的LyfecycleProcessor來啓動咱們註冊的SmartLifeCycle的子類。看一下代碼吧。

//默認的DefaultLifecycleProcessor.java
public void onRefresh() {
        startBeans(true);
        this.running = true;
    }
private void startBeans(boolean autoStartupOnly) {
        //獲取全部的LifeCycle類型的bean
        Map<String, Lifecycle> lifecycleBeans = getLifecycleBeans();
        Map<Integer, LifecycleGroup> phases = new HashMap<>();
        lifecycleBeans.forEach((beanName, bean) -> {
            //默認的DefaultLifecycleProcessor只會啓動SmartLifecycle的,或者非自動啓動的類型
        //SmartLifecycle繼承了Phases接口
            if (!autoStartupOnly || (bean instanceof SmartLifecycle && ((SmartLifecycle) bean).isAutoStartup())) {
                int phase = getPhase(bean);
                LifecycleGroup group = phases.get(phase);
                if (group == null) {
                    group = new LifecycleGroup(phase, this.timeoutPerShutdownPhase, lifecycleBeans, autoStartupOnly);
                     //添加到須要啓動的集合中
                    phases.put(phase, group);
                }
                group.add(beanName, bean);
            }
        });
        //啓動須要啓動的這些LifeCycle
        if (!phases.isEmpty()) {
            List<Integer> keys = new ArrayList<>(phases.keySet());
            Collections.sort(keys);
            for (Integer key : keys) {
                phases.get(key).start();
            }
        }
    }

這一步主要完成如下操做:

  • 完成容器的初始化過程,發佈相應事件。
  • 啓動容器的聲明週期處理器。管理容器聲明週期。
  • 發佈 ContextRefreshedEvent事件。
  • 啓動內嵌的Servlet容器。
  • 發佈容器啓動事件。

3總結

Spring刷新應用上下文操做簡要劃分爲12步操做流程:
1.準備刷新--->2.獲取刷新bean工廠--->3.準備bean工廠--->4.前處理bean工廠--->

5.調用bean工廠前處理器--->6.註冊bean前處理器--->7.初始化消息源--->8.初始化應用事件發佈器--->

9.刷新--->10.註冊監聽器--->11.完成bean工廠初始化--->12.完成刷新.

相關文章
相關標籤/搜索