Spring IOC容器啟動源碼分析

1. 引言


我們可以通過ApplicationContext創(chuàng)建IOC容器,它有很多個子類匿级,下面通過它的子類AnnotationConfigApplicationContext的創(chuàng)建來分析下IOC容器是如何創(chuàng)建并進行初始化的蟋滴。

ApplicationContext applicationContext = 
new AnnotationConfigApplicationContext(AopConfig.class);

AnnotationConfigApplicationContext創(chuàng)建的源碼如下:

public AnnotationConfigApplicationContext(Class<?>... annotatedClasses) {
    this();
    register(annotatedClasses);
    refresh();
}

這里refresh()方法是重點,它的源碼是:

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) {
            // 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();
        }
    }
}

refresh()方法中每一行都很重要痘绎,我們依次來進行分析津函。

2. prepareRefresh()


該方法主要是為IOC容器啟動做一些準備工作,設(shè)置容器的啟動時間孤页,closedactive標識尔苦。

  protected void prepareRefresh() {
    // Switch to active.
    this.startupDate = System.currentTimeMillis();
    this.closed.set(false);
    this.active.set(true);
    

    // 空方法,留給子類擴展行施,初始化 placeholder property
    initPropertySources();

    // 驗證一些必須的屬性
    getEnvironment().validateRequiredProperties();

    // Store pre-refresh ApplicationListeners...
    if (this.earlyApplicationListeners == null) {
        this.earlyApplicationListeners = new LinkedHashSet<>(this.applicationListeners);
    } else {
        // Reset local application listeners to pre-refresh state.
        this.applicationListeners.clear();
        this.applicationListeners.addAll(this.earlyApplicationListeners);
    }

    // Allow for the collection of early ApplicationEvents,
    // to be published once the multicaster is available...
    this.earlyApplicationEvents = new LinkedHashSet<>();
}

這里有個可以擴展的點允坚,我們可以通過重寫ApplicationContext來對自定義環(huán)境變量驗證,要求必須存在某個環(huán)境變量時才能啟動IOC容器蛾号。具體細節(jié)可以參考:https://blog.csdn.net/boling_cavalry/article/details/81474340

3. obtainFreshBeanFactory


obtainFreshBeanFactory()主要是獲取BeanFactory稠项,在獲取BeanFactory之前會先創(chuàng)建BeanFactory

先來看看BeanFactory是在什么地方創(chuàng)建的鲜结,我們回到AnnotationConfigApplicationContext創(chuàng)建的地方展运。

public AnnotationConfigApplicationContext(Class<?>... annotatedClasses) {
    this(); // 調(diào)用無參的構(gòu)造
    register(annotatedClasses);
    refresh();
}

無參構(gòu)造器默認會隱式地調(diào)用父類的無參構(gòu)造器方法活逆,AnnotationConfigApplicationContext的父類是GenericApplicationContext,而BeanFactory就是在GenericApplicationContext的構(gòu)造方法中創(chuàng)建出來的拗胜。

public GenericApplicationContext() {
    this.beanFactory = new DefaultListableBeanFactory();
}

再回到obtainFreshBeanFactory()方法蔗候,它主要做了3件事情:

  1. 設(shè)置refreshed屬性,通過AtomicBooleancas操作控制refresh()方法只會被調(diào)用一次埂软;
  2. beanFactory設(shè)置serializationId锈遥;
  3. 返回beanFactory對象,實際類型為DefaultListableBeanFactory勘畔。

4.prepareBeanFactory


prepareBeanFactory(beanFactory)主要功能是給上一步獲取到的beanFactory進行一些屬性的設(shè)置所灸。主要設(shè)置了以下屬性:

  • BeanFactory的類加載器、支持表達式解析器咖杂;
  • 添加了兩個BeanPostProcessorApplicationContextAwareProcessorApplicationListenerDetector蚊夫;
  • 設(shè)置忽略的自動裝配接口:EnvironmentAware诉字,EmbeddedValueResolverAwareResourceLoaderAware知纷,ApplicationEventPublisherAware壤圃,MessageSourceAwareApplicationContextAware琅轧, 在依賴注入的時候忽略這些接口伍绳,也就是這些指定的接口不會被注入進去。
  • 注冊可以解析的自動裝配:BeanFactory,ResourceLoader,ApplicationEventPublisher,ApplicationContext乍桂,這些類可以在任何地方直接注入冲杀;
  • 添加類加載期織入(LoadTimeWeaver)的AspectJ
  • 注冊一些組件:environment睹酌、systemProperties权谁、systemEnvironment

在Java 語言中憋沿,從織入切面的方式上來看旺芽,存在三種織入方式:編譯期織入、類加載期織入和運行期織入辐啄。編譯期織入是指在Java編譯期采章,采用特殊的編譯器,將切面織入到Java類中壶辜;而類加載期織入則指通過特殊的類加載器悯舟,在類字節(jié)碼加載到JVM時,織入切面砸民;運行期織入則是采用CGLib工具或JDK動態(tài)代理進行切面的織入图谷。

AspectJ提供了兩種切面織入方式翩活,第一種通過特殊編譯器,在編譯期便贵,將AspectJ語言編寫的切面類織入到Java類中菠镇,可以通過一個Ant或Maven任務(wù)來完成這個操作;第二種方式是類加載期織入承璃,也簡稱為LTW(Load Time Weaving)利耍。

5. postProcessBeanFactory


postProcessBeanFactory(beanFactory)是個空方法。子類可以通過重寫這個方法盔粹,在BeanFactory創(chuàng)建并預(yù)準備完成之后做些擴展工作隘梨。該方法在spring-web下有對其進行重寫。

6. invokeBeanFactoryPostProcessors


invokeBeanFactoryPostProcessors(beanFactory)主要用來執(zhí)行BeanFactoryPostProcessors舷嗡,它會將bean的信息轉(zhuǎn)化成BeanDefinition轴猎。

BeanFactoryPostProcessorsBeanFacotry的后置處理器,在BeanFactory標準初始化之后執(zhí)行进萄,它是Spring提供的眾多擴展點之一捻脖。BeanFacotry后置處理器有兩個接口:BeanFactoryPostProcessorBeanDefinitionRegistryPostProcessor

invokeBeanFactoryPostProcessors方法整體流程如下:

先執(zhí)行`BeanDefinitionRegistryPostProcessor`接口:
1. 獲取所有的`BeanDefinitionRegistryPostProcessor`中鼠;
2. 看先執(zhí)行實現(xiàn)了`PriorityOrdered`優(yōu)先級接口的`BeanDefinitionRegistryPostProcessor`可婶、         `postProcessor.postProcessBeanDefinitionRegistry(registry)`
3. 在執(zhí)行實現(xiàn)了`Ordered`順序接口的`BeanDefinitionRegistryPostProcessor`;
`postProcessor.postProcessBeanDefinitionRegistry(registry)`
4. 最后執(zhí)行沒有實現(xiàn)任何優(yōu)先級或者是順序接口的`BeanDefinitionRegistryPostProcessors`援雇;
`postProcessor.postProcessBeanDefinitionRegistry(registry)`
            
再執(zhí)行`BeanFactoryPostProcessor`的方法
1. 獲取所有的`BeanFactoryPostProcessor`
2. 看先執(zhí)行實現(xiàn)了`PriorityOrdered`優(yōu)先級接口的`BeanFactoryPostProcessor`矛渴、
`postProcessor.postProcessBeanFactory()`
3. 在執(zhí)行實現(xiàn)了`Ordered`順序接口的`BeanFactoryPostProcessor`;
`postProcessor.postProcessBeanFactory()`
4. 最后執(zhí)行沒有實現(xiàn)任何優(yōu)先級或者是順序接口的`BeanFactoryPostProcessor`惫搏;
`postProcessor.postProcessBeanFactory()`

7. registerBeanPostProcessors


registerBeanPostProcessors(beanFactory)方法用來向beanFactory注冊BeanPostProcessor(bean的后置處理器)具温,這又是Spring容器提供的眾多擴展點之一。Bean的后置處理器共有5個接口:

  1. BeanPostProcessor
  2. DestructionAwareBeanPostProcessor
  3. InstantiationAwareBeanPostProcessor
  4. SmartInstantiationAwareBeanPostProcessor
  5. MergedBeanDefinitionPostProcessor

這5個接口中的方法會在IOC容器啟動過程中不同的時機被回調(diào)筐赔。

BeanFacotryPostProcessor類似桂躏,BeanPostProcessor也能夠通過實現(xiàn)PriorityOrderedOrdered接口進行排序川陆。

registerBeanPostProcessors(beanFactory)方法中將BeanFacotryPostProcessor分成priorityOrderedPostProcessors剂习、internalPostProcessorsorderedPostProcessorNames较沪、nonOrderedPostProcessorNames 4 類鳞绕,分好類之后再依次添加BeanFactory中。

priorityOrderedPostProcessor: 實現(xiàn)了`PriorityOrdered`接口的BeanPostProcessor尸曼;
orderedPostProcessorNames: 實現(xiàn)了`Ordered`接口的BeanPostProcessor们何;
nonOrderedPostProcessorNames: 沒有實現(xiàn)排序的BeanPostProcessor
internalPostProcessors: MergedBeanDefinitionPostProcessor接口

通過請求beanFactory.addBeanPostProcessor(postProcessor);方法,向容器中添加bean的后置處理器控轿。

8. initMessageSource


initMessageSource()方法是向容器中注冊一個MessageSource組件冤竹。MessageSource主要作用是支持國際化拂封。

initMessageSource()方法的主要邏輯是:
先看容器中是否有namemessageSourceMessageSource的組件,

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 essageSource if no parent MessageSource
                // registered already.
                hms.setParentMessageSource(getInternalParentMessageSource());
            }
        }
}

如果容器中沒有MessageSource組件,則創(chuàng)建出來并注冊到beanFactory中鹦蠕。

DelegatingMessageSource dms = new DelegatingMessageSource();
dms.setParentMessageSource(getInternalParentMessageSource());
this.messageSource = dms;
beanFactory.registerSingleton(MESSAGE_SOURCE_BEAN_NAME, this.messageSource);

9. initApplicationEventMulticaster


initApplicationEventMulticaster()主要對事件派發(fā)器(ApplicationEventMulticaster)進行初始化冒签,即向beanFactory注冊一個事件派發(fā)器。它的邏輯很很簡單钟病,就是先判斷容器中是否有name=applicationEventMulticaster的bean萧恕,沒有的話就創(chuàng)建一個再向容器中注冊。

10. onRefresh


這個方法默認實現(xiàn)什么都沒有做肠阱,主要留給子類進行拓展票唆。

11. registerListeners


registerListeners() 將所有的ApplicationListener進行注冊,并進行事件派發(fā)屹徘。它的主要邏輯:

  1. 獲取所有的ApplicationListener走趋;
  2. 將每個監(jiān)聽器添加到事件派發(fā)器中;
  3. 如果存在早期應(yīng)用事件噪伊,則將其發(fā)布出去簿煌。

12. finishBeanFactoryInitialization


finishBeanFactoryInitialization(beanFactory)是個重點方法,它會將所有非懶加載的單例對象進行實例化酥宴。

AbstractApplicationContext#finishBeanFactoryInitialization方法中啦吧,它最終會調(diào)用DefaultListableBeanFactory#preInstantiateSingletons方法對剩下的單實例bean進行初始化,我們重點看看此方法。先貼一下源碼:

public void preInstantiateSingletons() throws BeansException {
    // beanDefinitionNames在refresh()之前創(chuàng)建ApplicationContext的this()方法中進行設(shè)值
    List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);

    // 遍歷觸發(fā)所有非懶加載的單例bean進行初始化
    for (String beanName : beanNames) {
        RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
        //單例鸵鸥、非抽象丽涩、非懶加載
        if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
            // bean是否為工廠bean,工廠bean需要加
            if (isFactoryBean(beanName)) {
                // 通過 &+beanName來獲取工廠bean本身藻懒,而beanName獲取的是FactoryBean創(chuàng)建的對象
                Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
                if (bean instanceof FactoryBean) {
                    final FactoryBean<?> factory = (FactoryBean<?>) bean;
                    boolean isEagerInit;
                    if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
                        isEagerInit = AccessController.doPrivileged((PrivilegedAction<Boolean>)
                                        ((SmartFactoryBean<?>) factory)::isEagerInit,
                                getAccessControlContext());
                    }
                    else {
                        isEagerInit = (factory instanceof SmartFactoryBean &&
                                ((SmartFactoryBean<?>) factory).isEagerInit());
                    }
                    if (isEagerInit) {
                        // 獲取FactoryBean創(chuàng)建的bean對象
                        getBean(beanName);
                    }
                }
            }
            else {
                // 普通的單例bean獲取對象,實際會進行初始化
                getBean(beanName);
            }
        }
    }

    // 觸發(fā)實現(xiàn)了SmartInitializingSingleton接口的afterSingletonsInstantiated方法
    for (String beanName : beanNames) {
        Object singletonInstance = getSingleton(beanName);
        if (singletonInstance instanceof SmartInitializingSingleton) {
            final SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
            if (System.getSecurityManager() != null) {
                AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
                    smartSingleton.afterSingletonsInstantiated();
                    return null;
                }, getAccessControlContext());
            }
            else {
                smartSingleton.afterSingletonsInstantiated();
            }
        }
    }
}

其中getBean()方法是重點,我們需要重點關(guān)注诚啃。getBean()是定義在AbstractBeanFactory類中的方法,getBean()方法最終會調(diào)用doGetBean()方法(Spring中很多類似的風(fēng)格私沮,真正干活的都放在doXxx方法中)始赎。

doGetBean方法中會完成bean的初始化,其大概邏輯是:先獲取緩存中保存的單實例Bean仔燕。如果能獲取到說明這個Bean之前被創(chuàng)建過(所有創(chuàng)建過的單實例Bean都會被緩存到名為singletonObjects的map中)造垛,如果獲取不到就進行Bean的創(chuàng)建流程,而在每個Bean創(chuàng)建的過程中又會觸發(fā)各種BeanPostProcessor的執(zhí)行晰搀。

12.1 獲取bean-doGetBean


下面來看看doGetBean的源碼:

protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
                          @Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
    // beanName轉(zhuǎn)換五辽,因為傳入的參數(shù)可以是alias,也可能是FactoryBean的name外恕,所以需要進行轉(zhuǎn)換
    final String beanName = transformedBeanName(name);
    Object bean;

    // 嘗試從緩存中獲取bean杆逗,這里緩存有三級緩存乡翅,主要用來解決循環(huán)依賴問題
    Object sharedInstance = getSingleton(beanName);
    if (sharedInstance != null && args == null) {
        bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
    } else {
        // 原型模式,如果存在循環(huán)依賴罪郊,則拋出異常
        if (isPrototypeCurrentlyInCreation(beanName)) {
            throw new BeanCurrentlyInCreationException(beanName);
        }

        // 獲取父BeanFactory
        BeanFactory parentBeanFactory = getParentBeanFactory();
        //如果當(dāng)前容器中沒有bean的定義信息蠕蚜,就從父容器中獲取
        if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
            // Not found -> check parent.
            String nameToLookup = originalBeanName(name);
            if (parentBeanFactory instanceof AbstractBeanFactory) {
                return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
                        nameToLookup, requiredType, args, typeCheckOnly);
            } else if (args != null) {
                // Delegation to parent with explicit args.
                return (T) parentBeanFactory.getBean(nameToLookup, args);
            } else if (requiredType != null) {
                // No args -> delegate to standard getBean method.
                return parentBeanFactory.getBean(nameToLookup, requiredType);
            } else {
                return (T) parentBeanFactory.getBean(nameToLookup);
            }
        }
        // 如果不僅僅是做類型檢查,標記bean的狀態(tài)已經(jīng)創(chuàng)建排龄,即將beanName加入alreadyCreated集合中
        if (!typeCheckOnly) {
            // 這個方法使用了雙重檢測機制
            markBeanAsCreated(beanName);
        }

        try {
            // 如果存在父bean波势,則同時合并父bean的相關(guān)屬性
            final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
            // 檢查bean是否是抽象的,是的話就拋出異常
            checkMergedBeanDefinition(mbd, beanName, args);

            // 加載當(dāng)前bean依賴的bean
            String[] dependsOn = mbd.getDependsOn();
            if (dependsOn != null) {
                for (String dep : dependsOn) {
                    if (isDependent(beanName, dep)) {
                        throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                                "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
                    }
                    // 緩存依賴調(diào)用
                    registerDependentBean(dep, beanName);
                    try {
                        getBean(dep);
                    } catch (NoSuchBeanDefinitionException ex) {
                        throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                                "'" + beanName + "' depends on missing bean '" + dep + "'", ex);
                    }
                }
            }

            // 處理單例bean
            if (mbd.isSingleton()) {
                sharedInstance = getSingleton(beanName, () -> {
                    try {
                        // 實際創(chuàng)建beand的地方
                        return createBean(beanName, mbd, args);
                    } catch (BeansException ex) {
                        // 從單例緩存中移除
                        destroySingleton(beanName);
                        throw ex;
                    }
                });
                bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
            } else if (mbd.isPrototype()) {
                // scope==prototype的bean 創(chuàng)建新的實例.
                Object prototypeInstance = null;
                try {
                    // 設(shè)置正在創(chuàng)建的狀態(tài)
                    beforePrototypeCreation(beanName);
                    // 創(chuàng)建bean
                    prototypeInstance = createBean(beanName, mbd, args);
                } finally {
                    afterPrototypeCreation(beanName);
                }
                // 返回對應(yīng)的實例
                bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
            } else {
                // 其他scope的bean
                String scopeName = mbd.getScope();
                // scope合法性校驗
                final Scope scope = this.scopes.get(scopeName);
                if (scope == null) {
                    throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
                }
                try {
                    Object scopedInstance = scope.get(beanName, () -> {
                        beforePrototypeCreation(beanName);
                        try {
                            return createBean(beanName, mbd, args);
                        } finally {
                            afterPrototypeCreation(beanName);
                        }
                    });
                    bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
                } catch (IllegalStateException ex) {
                    throw new BeanCreationException(beanName,
                            "Scope '" + scopeName + "' is not active for the current thread; consider " +
                                    "defining a scoped proxy for this bean if you intend to refer to it from a singleton",
                            ex);
                }
            }
        } catch (BeansException ex) {
            cleanupAfterBeanCreationFailure(beanName);
            throw ex;
        }
    }

    // 如果對返回 bean 類型有要求橄维,則進行類型檢查尺铣,并按需做類型轉(zhuǎn)換
    if (requiredType != null && !requiredType.isInstance(bean)) {
        try {
            // 執(zhí)行類型轉(zhuǎn)換,轉(zhuǎn)換成期望的類型
            T convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType);
            if (convertedBean == null) {
                throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
            }
            return convertedBean;
        } catch (TypeMismatchException ex) {
            throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
        }
    }
    return (T) bean;
}

整個方法可以概括為:

1争舞、轉(zhuǎn)換Bean的名稱凛忿,獲取真正的beanName;
2竞川、檢查三級緩存中是否含有bean店溢,如果含有則實例化并返回對象,否則繼續(xù)流程委乌;
3床牧、如果當(dāng)前beanFactory中不存在需要的bean,則從父容器中獲取bean遭贸;
4戈咳、如果當(dāng)前bean存在依賴的bean,就遍歷初始化依賴的bean對象壕吹;
5著蛙、根據(jù)bean的作用域不同,對bean進行實例化耳贬,作用域分為:singleton踏堡、prototype和其他;
6咒劲、如果requiredType不為空顷蟆,則做類型校驗,如果需要類型和實際類型不一致腐魂,則做類型轉(zhuǎn)換帐偎;
7、返回bean對象挤渔。

12.2 bean的創(chuàng)建--createBean

上面doGetBean方法中肮街,創(chuàng)建bean的工作是調(diào)用AbstractAutowireCapableBeanFactory#createBean來完成的,以下是createBean的源碼(省略日志輸出和異常處理):

protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
        throws BeanCreationException {

    RootBeanDefinition mbdToUse = mbd;

    // 根據(jù)設(shè)置的class屬性或className來解析得到Class引用
    Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
    if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
        mbdToUse = new RootBeanDefinition(mbd);
        mbdToUse.setBeanClass(resolvedClass);
    }

    // 處理lookup-method和replaced-method標簽
    try {
        mbdToUse.prepareMethodOverrides();
    }

    // 處理InstantiationAwareBeanPostProcessor判导,讓BeanPostProcessor先攔截返回代理對象
    try {
        // Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
        Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
        if (bean != null) {
            return bean;
        }
    }

    // 創(chuàng)建bean實例
    try {
        Object beanInstance = doCreateBean(beanName, mbdToUse, args);
        if (logger.isTraceEnabled()) {
            logger.trace("Finished creating instance of bean '" + beanName + "'");
        }
        return beanInstance;
    }
}

該方法雖然叫createBean嫉父,但還不是真正創(chuàng)建bean的地方沛硅,它主要還是在做一些前期的準備工作,具體創(chuàng)建bean的方法是doCreateBean绕辖。在看doCreateBean方法之前摇肌,會調(diào)用resolveBeforeInstantiation()方法。

protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
    Object bean = null;
    if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
        // mbd是程序創(chuàng)建的且存在后置處理器
        if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
            // 獲取最終的class引用仪际,如果是工廠方法則獲取工廠所創(chuàng)建的實例類型
            Class<?> targetType = determineTargetType(beanName, mbd);
            if (targetType != null) {
                // 調(diào)用實例化前置處理
                bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
                if (bean != null) {
                    // 調(diào)用初始化后置處理
                    bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
                }
            }
        }
        mbd.beforeInstantiationResolved = (bean != null);
    }
    return bean;
}

可以看到如果InstantiationAwareBeanPostProcessor中的實例化前置處理方法的返回值不為空围小,就會直接請求BeanPostProcessor接口中的初始化后置處理方法。而如果這個方法的最終返回值bean不為空树碱,則會跳過后續(xù)的doCreateBean方法執(zhí)行(因為bean已經(jīng)創(chuàng)建完成了)肯适,從而形式短路。

12.2.1 doCreateBean

從上面的分析成榜,我們知道:createBean只是在做創(chuàng)建bean之前的準備工作框舔,真正創(chuàng)建bean的方法是doCreateBean

protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
        throws BeanCreationException {

    // 如果是單例赎婚,嘗試獲取對應(yīng)的BeanWrapper.
    BeanWrapper instanceWrapper = null;
    if (mbd.isSingleton()) {
        instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
    }
    // BeanWrapper為空刘绣,即bean未實例化,則創(chuàng)建bean實例
    if (instanceWrapper == null) {
        // 使用對應(yīng)的策略(工廠方法挣输、構(gòu)造函數(shù))創(chuàng)建bean實例
        instanceWrapper = createBeanInstance(beanName, mbd, args);
    }
    final Object bean = instanceWrapper.getWrappedInstance();
    Class<?> beanType = instanceWrapper.getWrappedClass();
    if (beanType != NullBean.class) {
        mbd.resolvedTargetType = beanType;
    }

    // Allow post-processors to modify the merged bean definition.
    // 應(yīng)用MergedBeanDefinitionPostProcessor
    synchronized (mbd.postProcessingLock) {
        if (!mbd.postProcessed) {
            try {
                // 處理merged bean
                applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
            } catch (Throwable ex) {
                throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                        "Post-processing of merged bean definition failed", ex);
            }
            mbd.postProcessed = true;
        }
    }

    // Eagerly cache singletons to be able to resolve circular references
    // even when triggered by lifecycle interfaces like BeanFactoryAware.
    // 檢查是否需要提前暴露纬凤,避免循環(huán)依賴
    boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
            isSingletonCurrentlyInCreation(beanName));
    if (earlySingletonExposure) {
        // 為避免循環(huán)依賴,在bean實例化完成之前撩嚼,將對應(yīng)的ObjectFactory添加到singletonFactories屬性中
        addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
    }

    // 初始化Bean實例.
    Object exposedObject = bean;
    try {
        // 對bean的屬性進行填充停士,注入屬性值
        populateBean(beanName, mbd, instanceWrapper);
        // 初始化Bean,調(diào)用各種初始化方法
        exposedObject = initializeBean(beanName, exposedObject, mbd);
    } catch (Throwable ex) {
        if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
            throw (BeanCreationException) ex;
        } else {
            throw new BeanCreationException(
                    mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
        }
    }

    // 再次驗證是否存在依賴關(guān)系
    if (earlySingletonExposure) {
        // 獲取單例bean绢馍,不允許早期引用
        Object earlySingletonReference = getSingleton(beanName, false);
        if (earlySingletonReference != null) {
            if (exposedObject == bean) {
                exposedObject = earlySingletonReference;
            } else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
                // 獲取依賴的bean name
                String[] dependentBeans = getDependentBeans(beanName);
                Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
                for (String dependentBean : dependentBeans) {
                    if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
                        actualDependentBeans.add(dependentBean);
                    }
                }
                // bean在創(chuàng)建完成之后向瓷,其依賴的bean一定是被創(chuàng)建了的
                // 如果actualDependentBeans不為空肠套,則說明bean依賴的bean沒有完成創(chuàng)建舰涌,存在循環(huán)依賴
                if (!actualDependentBeans.isEmpty()) {
                    throw new BeanCurrentlyInCreationException(beanName,
                            "Bean with name '" + beanName + "' has been injected into other beans [" +
                                    StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +
                                    "] in its raw version as part of a circular reference, but has eventually been " +
                                    "wrapped. This means that said other beans do not use the final version of the " +
                                    "bean. This is often the result of over-eager type matching - consider using " +
                                    "'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.");
                }
            }
        }
    }

    // Register bean as disposable.
    // 注冊DisposableBean
    try {
        registerDisposableBeanIfNecessary(beanName, bean, mbd);
    } catch (BeanDefinitionValidationException ex) {
        throw new BeanCreationException(
                mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
    }

    return exposedObject;
}

doCreateBean方法概括起來,主要分為以下步驟:

1)你稚、`創(chuàng)建Bean實例`:createBeanInstance(beanName, mbd, args);利用工廠方法或者對象的構(gòu)造器創(chuàng)建出Bean實例瓷耙;
2)、applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName):調(diào)用MergedBeanDefinitionPostProcessor的postProcessMergedBeanDefinition(mbd, beanType, beanName);
3)刁赖、檢查是否需要提前曝光搁痛,避免循環(huán)依賴
4)、`Bean屬性賦值`:populateBean(beanName, mbd, instanceWrapper);
    賦值之前:
    1)宇弛、調(diào)用InstantiationAwareBeanPostProcessor后置處理器的postProcessAfterInstantiation()鸡典;
    2)、調(diào)用InstantiationAwareBeanPostProcessor后置處理器的postProcessPropertyValues()枪芒;
    賦值之后:
    3)彻况、應(yīng)用Bean屬性的值谁尸,為屬性利用setter方法等進行賦值;
    applyPropertyValues(beanName, mbd, bw, pvs);
5)纽甘、`Bean初始化`:initializeBean(beanName, exposedObject, mbd);
    1)良蛮、【執(zhí)行Aware接口方法】invokeAwareMethods(beanName, bean); 執(zhí)行xxxAware接口的方法BeanNameAware\BeanClassLoaderAware\BeanFactoryAware
    2)、【執(zhí)行后置處理器postProcessBeforeInitialization】applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName); BeanPostProcessor.postProcessBeforeInitialization();
    3)悍赢、【執(zhí)行初始化方法】invokeInitMethods(beanName, wrappedBean, mbd);
        1)决瞳、是否是InitializingBean接口的實現(xiàn);執(zhí)行接口規(guī)定的初始化左权;
        2)皮胡、是否自定義初始化方法;
    4)赏迟、【執(zhí)行后置處理器postProcessAfterInitialization】applyBeanPostProcessorsAfterInitialization: BeanPostProcessor.postProcessAfterInitialization()胸囱;
6)、再次驗證是否存在循環(huán)依賴瀑梗;
7)烹笔、注冊 DisposableBean。

13.finishRefresh


finishRefresh()完成IOC容器的創(chuàng)建抛丽。

protected void finishRefresh() {
    // Clear context-level resource caches (such as ASM metadata from scanning).
    clearResourceCaches();

    // 初始化一個和生命周期相關(guān)的后置處理器LifecycleProcessor谤职,默認從容器中找,沒找到就創(chuàng)建一個
    initLifecycleProcessor();

    // 回調(diào)LifecycleProcessor的onRefresh方法
    getLifecycleProcessor().onRefresh();

    // 發(fā)布容器刷新完成事件
    publishEvent(new ContextRefreshedEvent(this));

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

至此亿鲜,SpringIOC容器就創(chuàng)建完畢允蜈。

寫了一天,有點寫不動了蒿柳。先這樣吧饶套,后續(xù)有精力再進行更新吧。

參考

https://my.oschina.net/wangzhenchao/blog/918237

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末垒探,一起剝皮案震驚了整個濱河市妓蛮,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌圾叼,老刑警劉巖蛤克,帶你破解...
    沈念sama閱讀 216,372評論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異夷蚊,居然都是意外死亡构挤,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,368評論 3 392
  • 文/潘曉璐 我一進店門惕鼓,熙熙樓的掌柜王于貴愁眉苦臉地迎上來筋现,“玉大人,你說我怎么就攤上這事》桑” “怎么了彻犁?”我有些...
    開封第一講書人閱讀 162,415評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長凰慈。 經(jīng)常有香客問我汞幢,道長,這世上最難降的妖魔是什么微谓? 我笑而不...
    開封第一講書人閱讀 58,157評論 1 292
  • 正文 為了忘掉前任森篷,我火速辦了婚禮,結(jié)果婚禮上豺型,老公的妹妹穿的比我還像新娘仲智。我一直安慰自己,他們只是感情好姻氨,可當(dāng)我...
    茶點故事閱讀 67,171評論 6 388
  • 文/花漫 我一把揭開白布钓辆。 她就那樣靜靜地躺著,像睡著了一般肴焊。 火紅的嫁衣襯著肌膚如雪前联。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,125評論 1 297
  • 那天娶眷,我揣著相機與錄音似嗤,去河邊找鬼。 笑死届宠,一個胖子當(dāng)著我的面吹牛烁落,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播豌注,決...
    沈念sama閱讀 40,028評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼伤塌,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了轧铁?” 一聲冷哼從身側(cè)響起每聪,我...
    開封第一講書人閱讀 38,887評論 0 274
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎属桦,沒想到半個月后熊痴,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體他爸,經(jīng)...
    沈念sama閱讀 45,310評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡聂宾,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,533評論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了诊笤。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片系谐。...
    茶點故事閱讀 39,690評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出纪他,到底是詐尸還是另有隱情鄙煤,我是刑警寧澤,帶...
    沈念sama閱讀 35,411評論 5 343
  • 正文 年R本政府宣布茶袒,位于F島的核電站梯刚,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏薪寓。R本人自食惡果不足惜亡资,卻給世界環(huán)境...
    茶點故事閱讀 41,004評論 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望向叉。 院中可真熱鬧锥腻,春花似錦、人聲如沸母谎。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽奇唤。三九已至幸斥,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間咬扇,已是汗流浹背睡毒。 一陣腳步聲響...
    開封第一講書人閱讀 32,812評論 1 268
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留冗栗,地道東北人演顾。 一個月前我還...
    沈念sama閱讀 47,693評論 2 368
  • 正文 我出身青樓,卻偏偏與公主長得像隅居,于是被迫代替她去往敵國和親钠至。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,577評論 2 353

推薦閱讀更多精彩內(nèi)容