spring源碼:Spring IoC 容器初始化過程

自我感覺spring在面試當(dāng)中很常見,仔細(xì)整理了一下:

1 BeanDefinition的Resource定位 
2 BeanDefinition的載入 
3 向IoC容器注冊BeanDefinition

Spring IoC 容器初始化的關(guān)鍵環(huán)節(jié)就在 AbstractApplicationContext的refresh() ?法中

1.主流程

@Override

public void refresh() throws BeansException, IllegalStateException {

    synchronized (this.startupShutdownMonitor) {

        // 第?步:刷新前的預(yù)處理

        prepareRefresh();

       /*

        第?步:

        獲取BeanFactory;默認(rèn)實(shí)現(xiàn)是DefaultListableBeanFactory

        加載BeanDefinition 并注冊到 BeanDefitionRegistry

        */ ConfigurableListableBeanFactory beanFactory =

        obtainFreshBeanFactory();

        // 第三步:BeanFactory的預(yù)準(zhǔn)備?作(BeanFactory進(jìn)??些設(shè)置,?如context的類加載器等)
        prepareBeanFactory(beanFactory);
        try {
            // 第四步:BeanFactory準(zhǔn)備?作完成后進(jìn)?的后置處理?作
            postProcessBeanFactory(beanFactory);
            // 第五步:實(shí)例化并調(diào)?實(shí)現(xiàn)了BeanFactoryPostProcessor接?的Bean
            invokeBeanFactoryPostProcessors(beanFactory);
            // 第六步:注冊BeanPostProcessor(Bean的后置處理器),在創(chuàng)建bean的前后等執(zhí)?
            registerBeanPostProcessors(beanFactory);
            // 第七步:初始化MessageSource組件(做國際化功能;消息綁定,消息解析);
            initMessageSource();

            // 第?步:初始化事件派發(fā)器
            initApplicationEventMulticaster();

            // 第九步:?類重寫這個(gè)?法,在容器刷新的時(shí)候可以?定義邏輯
            onRefresh();

            // 第?步:注冊應(yīng)?的監(jiān)聽器。就是注冊實(shí)現(xiàn)了ApplicationListener接?的監(jiān)聽器bean
            registerListeners();

        /*

        第??步:
        初始化所有剩下的?懶加載的單例bean
        初始化創(chuàng)建?懶加載?式的單例Bean實(shí)例(未設(shè)置屬性)
                填充屬性
                初始化?法調(diào)?(?如調(diào)?afterPropertiesSet?法、init-method?法)
                調(diào)?BeanPostProcessor(后置處理器)對實(shí)例bean進(jìn)?后置處
        */
            finishBeanFactoryInitialization(beanFactory);
        /*
        第??步:
        完成context的刷新。主要是調(diào)?LifecycleProcessor的onRefresh()?法,并且發(fā)布事件(ContextRefreshedEvent)
        */
            finishRefresh();
      }
.......
   }
}

2.BeanFactory創(chuàng)建流程

2.1獲取BeanFactory子流程

QQ截圖20200706120004.png

上面流程中的第二步的方法: obtainFreshBeanFactory()

protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
    refreshBeanFactory();
    return getBeanFactory();
}

refreshBeanFactory()在AbstractRefreshableApplicationContext類中

protected final void refreshBeanFactory() throws BeansException {
    // 判斷是否已有bean factory
    if (hasBeanFactory()) {
        // 銷毀beans
        destroyBeans();
        // 關(guān)閉bean factory
        closeBeanFactory();
    }
    try {
    // 實(shí)例化DefaultListableBeanFactory  劃重點(diǎn):創(chuàng)建了beanFacory:DefaultListableBeanFactory 
        DefaultListableBeanFactory beanFactory = createBeanFactory();
        // 設(shè)置序列化id
        beanFactory.setSerializationId(getId());
        // 自定義bean工廠的一些屬性(如多個(gè)xml中的bean的id相同時(shí)是否覆蓋,是否允許循環(huán)依賴)
        customizeBeanFactory(beanFactory);
        // 加載應(yīng)用中的BeanDefinitions   劃重點(diǎn):加載所有bean的BeanDefinitions
        loadBeanDefinitions(beanFactory);
        synchronized (this.beanFactoryMonitor) {
            // 賦值當(dāng)前beanFactory
            this.beanFactory = beanFactory;
        }
    }
    ....
}

QQ截圖20200710190950.png

2.2加載解析BeanDefinition以及其注冊

上面代碼中AbstractRefreshableApplicationContext中的loadBeanDefinitions()方法加載

protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
     //給指定的beanFactory創(chuàng)建一個(gè)XmlBeanDefinitionReader讀取器對象,用于讀取解析xml對象
    XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
    
    //給XmlBeanDefinitionReader對象設(shè)置一些context上下文中的環(huán)境屬性
    beanDefinitionReader.setEnvironment(this.getEnvironment());
    beanDefinitionReader.setResourceLoader(this);
    beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));

     //提供給子類實(shí)現(xiàn),提供一些自定義的初始化策略
    initBeanDefinitionReader(beanDefinitionReader);
    // 真正的去加載BeanDefinition
    loadBeanDefinitions(beanDefinitionReader);
}

protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException {
    // 從Resource資源對象加載BeanDefinitions
    Resource[] configResources = getConfigResources();
    if (configResources != null) {
        reader.loadBeanDefinitions(configResources);
    }
    // 從xml配置文件加載BeanDefinition對象
    String[] configLocations = getConfigLocations();
    if (configLocations != null) {
              //跳轉(zhuǎn)至XmlBeanDefinitionReader中去加載
        reader.loadBeanDefinitions(configLocations);
    }
}

XmlBeanDefinitionReader類中加載代碼

public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException {
    ......
    try {
        InputStream inputStream = encodedResource.getResource().getInputStream();
        try {
            // 把xml文件流封裝為InputSource對象
            InputSource inputSource = new InputSource(inputStream);
            if (encodedResource.getEncoding() != null) {
                inputSource.setEncoding(encodedResource.getEncoding());
            }
            // do!執(zhí)行加載邏輯
            return doLoadBeanDefinitions(inputSource, encodedResource.getResource());
        }
    ......

doLoadBeanDefinitions:真正加載的方法:

protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
        throws BeanDefinitionStoreException {
    try {
        // 讀取xml信息,將xml中信息保存到Document對象中
        Document doc = doLoadDocument(inputSource, resource);
        // 解析Document對象,封裝成BeanDefinition對象并進(jìn)行注冊
        int count = registerBeanDefinitions(doc, resource);
        if (logger.isDebugEnabled()) {
            logger.debug("Loaded " + count + " bean definitions from " + resource);
        }
        return count;
    }
    ......
}

我們重點(diǎn)觀察XmlBeanDefinitionReader類的registerBeanDefinitions方法,期間產(chǎn)生了多次重載調(diào)用,我們定位到最后一個(gè)

public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
    BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
    // 獲取已有BeanDefinition的數(shù)量
    int countBefore = getRegistry().getBeanDefinitionCount();
    // 注冊BeanDefinition(createReaderContex()首先完成了NamespaceHandlerResolver的初始化。)
    documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
    // 返回新注冊的BeanDefinition數(shù)量
    return getRegistry().getBeanDefinitionCount() - countBefore;
}

進(jìn)入registerBeanDefinitions,再進(jìn)入DefaultBeanDefinitionDocumentReader類中的doRegisterBeanDefinitions()方法

protected void doRegisterBeanDefinitions(Element root) {
    ......
    preProcessXml(root);
    // 解析BeanDefinition
    parseBeanDefinitions(root, this.delegate);
    postProcessXml(root);
    this.delegate = parent;
}

查看parseBeanDefinitions()方法,解析xml中的<bean>等標(biāo)簽

protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
    if (delegate.isDefaultNamespace(root)) {
        NodeList nl = root.getChildNodes();
        for (int i = 0; i < nl.getLength(); i++) {
            Node node = nl.item(i);
            if (node instanceof Element) {
                Element ele = (Element) node;
                if (delegate.isDefaultNamespace(ele)) {
                    // 解析默認(rèn)標(biāo)簽元素
                    parseDefaultElement(ele, delegate);
                }
                else {
                    // 解析自定義標(biāo)簽元素
                    delegate.parseCustomElement(ele);
        ......
}

查看分類處理方法parseDefaultElement(ele, delegate);

private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
    // import元素處理
    if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) {
        importBeanDefinitionResource(ele);
    }
    // alias元素處理
    else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) {
        processAliasRegistration(ele);
    }
    // bean元素處理
    else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) {
        processBeanDefinition(ele, delegate);
    }
    // 嵌套beans處理
    else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {
        // recurse
        doRegisterBeanDefinitions(ele);
    }
}

具體解析注冊bean的方法:processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate)

protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
    // 解析bean元素為BeanDefinition,但是此時(shí)使用BeanDefinitionHoler 又包裝成了BeanDefinitionHoler對象
    BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
    if (bdHolder != null) {
        // 如果有自定義標(biāo)簽,則處理自定義標(biāo)簽
        bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
        try {
            // Register the final decorated instance.
            // 完成BeanDefinition的注冊
            BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
        }
        .....
        getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
    }
}

查看BeanDefinitionReaderUtils的registerBeanDefinition()方法,然后一直跟蹤registerBeanDefinition方法直到下面這個(gè)方法中看到this.beanDefinitionMap.put(beanName, beanDefinition);將他放入beanDefinitionMap(是一個(gè) ConcurrentHashMap),完成注冊。

public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
        throws BeanDefinitionStoreException {

    ......
    BeanDefinition existingDefinition = this.beanDefinitionMap.get(beanName);
    if (existingDefinition != null) {
        ......
        // 劃重點(diǎn):將beanDefinition存入map集合
        this.beanDefinitionMap.put(beanName, beanDefinition);
    }
    ...
}

至此,注冊流程結(jié)束,我們發(fā)現(xiàn),所謂的注冊就是把封裝的XML中定義的Bean信息封裝為BeanDefinition對象之后放入-個(gè)Map中, BeanFactory 是以Map的結(jié)構(gòu)存放這些BeanDefinition的。
BeanDefinition和BeanDefinitionHolder的結(jié)構(gòu)


QQ截圖20200710190905.png

QQ截圖20200710190950.png

3.Bean創(chuàng)建流程

?流程??在AbstractApplicationContext#refresh()?finishBeanFactoryInitialization(beanFactory) 處
進(jìn)入方法,還在當(dāng)前類中:

protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
        beanFactory.setTempClassLoader(null);

        // Allow for caching all bean definition metadata, not expecting further changes.
        beanFactory.freezeConfiguration();

        // 實(shí)例化所有立即加載的單例bean
        beanFactory.preInstantiateSingletons();
    }

繼續(xù)進(jìn)?DefaultListableBeanFactory類的preInstantiateSingletons?法

public void preInstantiateSingletons() throws BeansException {
    ......
        synchronized (this.beanDefinitionMap) {
            for (Iterator it = this.beanDefinitionNames.iterator(); it.hasNext();) {
                String beanName = (String) it.next();
                RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
                if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
                                      //判斷是否是工廠bean
                    if (isFactoryBean(beanName)) {
                        FactoryBean factory = (FactoryBean) getBean(FACTORY_BEAN_PREFIX + beanName);
                        if (factory instanceof SmartFactoryBean && ((SmartFactoryBean) factory).isEagerInit()) {
                                                //通過getbean獲取實(shí)例
                            getBean(beanName);
                        }
                    }
                    else {
                                              //通過getbean獲取實(shí)例
                        getBean(beanName);
                    }
                }
            }
        }
    }

可以看出不管是工廠bean還是普通bean都是通過getBean獲取實(shí)例
進(jìn)入getBean(),只是轉(zhuǎn)發(fā)調(diào)用,最終進(jìn)入AbstractBeanFactory類的doGetBean

protected Object doGetBean(
            final String name, final Class requiredType, final Object[] args, boolean typeCheckOnly) throws BeansException {
  ......
  String[] dependsOn = mbd.getDependsOn();
    if (dependsOn != null) {
        for (int i = 0; i < dependsOn.length; i++) {
            String dependsOnBean = dependsOn[i];
            getBean(dependsOnBean);
            registerDependentBean(dependsOnBean, beanName);
        }
    }

    //劃重點(diǎn) Create bean instance.創(chuàng)建單例bean
    if (mbd.isSingleton()) {
        sharedInstance = getSingleton(beanName, new ObjectFactory() {
            public Object getObject() throws BeansException {
                try {
                                        //劃重點(diǎn) 創(chuàng)建bean
                    return createBean(beanName, mbd, args);
                }
                catch (BeansException ex) {
                    // Explicitly remove instance from singleton cache: It might have been put there
                    // eagerly by the creation process, to allow for circular reference resolution.
                    // Also remove any beans that received a temporary reference to the bean.
                    destroySingleton(beanName);
                    throw ex;
                }
            }
        });
        bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
    }

}

進(jìn)?到AbstractAutowireCapableBeanFactory類的?法,找到以下代碼部分


QQ截圖20200713115103.png

進(jìn)?doCreateBean?法

              if (instanceWrapper == null) {
                        //創(chuàng)建bean實(shí)例,但是尚未設(shè)置屬性
            instanceWrapper = createBeanInstance(beanName, mbd, args);
        }
        final Object bean = (instanceWrapper != null ? instanceWrapper.getWrappedInstance() : null);
        Class beanType = (instanceWrapper != null ? instanceWrapper.getWrappedClass() : null);

        // Allow post-processors to modify the merged bean definition.
        synchronized (mbd.postProcessingLock) {
            if (!mbd.postProcessed) {
                applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
                mbd.postProcessed = true;
            }
        }
        boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
                isSingletonCurrentlyInCreation(beanName));
                //判斷二級緩存
        if (earlySingletonExposure) {
            if (logger.isDebugEnabled()) {
                logger.debug("Eagerly caching bean '" + beanName +
                        "' to allow for resolving potential circular references");
            }
            addSingletonFactory(beanName, new ObjectFactory() {
                public Object getObject() throws BeansException {
                    return getEarlyBeanReference(beanName, mbd, bean);
                }
            });
        }

        // 重點(diǎn):給Bean填充屬性,調(diào)?初始化?法,應(yīng)?BeanPostProcessor后置處理器
        Object exposedObject = bean;
        try {
                        //bean屬性填充
            populateBean(beanName, mbd, instanceWrapper);
                        //掉用初始化方法,應(yīng)用BeanPostprocessor后置處理器
            exposedObject = initializeBean(beanName, exposedObject, mbd);
        }
        catch (Throwable ex) {
                }
    ......

bean實(shí)例化的時(shí)候如果存在bean之間互相依賴,使用三級緩存解決非構(gòu)造單例bean循環(huán)依賴問題,具體請看下一篇文章

4. lazy-init 延遲加載機(jī)制原理

普通 Bean 的初始化是在容器啟動(dòng)初始化階段執(zhí)?的,?被lazy-init=true修飾的 bean 則是在從容器?
第?次進(jìn)?context.getBean() 時(shí)進(jìn)?觸發(fā)。Spring 啟動(dòng)的時(shí)候會(huì)把所有bean信息(包括XML和注解)解
析轉(zhuǎn)化成Spring能夠識(shí)別的BeanDefinition并存到Hashmap?供下?的初始化時(shí)?,然后對每個(gè)
BeanDefinition 進(jìn)?處理,如果是懶加載的則在容器初始化階段不處理,其他的則在容器初始化階段進(jìn)
?初始化并依賴注?

public void preInstantiateSingletons() throws BeansException {
        // 所有beanDefinition集合
        List<String> beanNames = new ArrayList<String>(this.beanDefinitionNames);
        // 觸發(fā)所有?懶加載單例bean的初始化
        for (String beanName : beanNames) {
            // 獲取bean 定義
            RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
            // 判斷是否是懶加載單例bean,如果是單例的并且不是懶加載的則在容器創(chuàng)建時(shí)初始化
            if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
                // 判斷是否是 FactoryBean
                if (isFactoryBean(beanName)) {
                    final FactoryBean<?> factory = (FactoryBean<?>)
                            getBean(FACTORY_BEAN_PREFIX + beanName);
                    boolean isEagerInit;
                    if (System.getSecurityManager() != null && factory instanceof
                            SmartFactoryBean) {
                        isEagerInit = AccessController.doPrivileged(new
                       PrivilegedAction<Boolean>() {
                       @Override
                           public Boolean run() {
                                 return ((SmartFactoryBean<?>) factory).isEagerInit();
                             }
                          }, getAccessControlContext());
                   }                                                 
                } else {
                 /*
                  劃重點(diǎn)
                 如果是普通bean則進(jìn)?初始化并依賴注?,此 getBean(beanName)接下來觸發(fā)的邏輯
                和懶加載時(shí) context.getBean("beanName") 所觸發(fā)的邏輯是?樣的
                 */
                    getBean(beanName);
                }
            }
        }
    }

總結(jié)

對于被修飾為lazy-init的bean Spring 容器初始化階段不會(huì)進(jìn)? init 并且依賴注?,當(dāng)?shù)?次
進(jìn)?getBean時(shí)候才進(jìn)?初始化并依賴注?
對于?懶加載的bean,getBean的時(shí)候會(huì)從緩存?頭獲取,因?yàn)槿萜鞒跏蓟A段 Bean 已經(jīng)
初始化完成并緩存了起來

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容