Spring學(xué)習(xí)2-Bean的加載過(guò)程(IOC實(shí)現(xiàn)原理)

之前基本理清了ClassPathXmlApplicationContext的繼承層次,但一些重點(diǎn)方法和一些重要對(duì)象并未觸及,本文繼續(xù)調(diào)試和閱讀spring源碼,希望通過(guò)此次學(xué)習(xí)可以搞明白bean的加載和生成機(jī)制。調(diào)試的Main方法如下殴泰,很簡(jiǎn)單,實(shí)現(xiàn)了一個(gè)簡(jiǎn)單的Transaction對(duì)象叫挟,使用ClassPathXmlApplicationContext獲取transaction對(duì)象艰匙,調(diào)用對(duì)象的transaction方法。

import com.thoughtworks.Transaction;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.core.io.DefaultResourceLoader;
import org.springframework.core.io.Resource;

import java.io.IOException;

public class Main {

    public static void main(String[] args) throws IOException {
        ApplicationContext context = new ClassPathXmlApplicationContext("Application-context.xml");
        Transaction transaction = (Transaction)context.getBean("transaction");
        transaction.transaction();
    }
}

下面是Transaction對(duì)象定義抹恳,其中stMapper用到了mybatis员凝,mybatis是比較流行的orm框架,之前也沒(méi)使用過(guò)奋献,由于項(xiàng)目中使用健霹,模仿著寫(xiě)了一個(gè)旺上,如果可以的話,順便將mybatis與spring的整合代碼一起看了糖埋。trasaction方法上我加上了@Transactional注解宣吱,這個(gè)注解實(shí)現(xiàn)從spring框架中支持了數(shù)據(jù)庫(kù)事務(wù),好處在于讓程序員避免了在每次提交事務(wù)sql時(shí)寫(xiě)那些模板代碼瞳别,通過(guò)與mybatis的整合征候,針對(duì)數(shù)據(jù)庫(kù)的操作看起來(lái)會(huì)相當(dāng)干凈,僅僅加上一個(gè)注解祟敛,就可以輕松實(shí)現(xiàn)對(duì)事物的控制疤坝。這里加上@Transactional注解,是想了解下spring的實(shí)現(xiàn)機(jī)制馆铁,之前看了一點(diǎn)這塊的代碼跑揉,了解到spring的事務(wù)本質(zhì)實(shí)際上還是AOP的方式實(shí)現(xiàn)(Spring AOP通過(guò)動(dòng)態(tài)代理的方式實(shí)現(xiàn),動(dòng)態(tài)代理本質(zhì)就是動(dòng)態(tài)生成繼承接口的類(lèi)或者繼承父類(lèi)的子類(lèi)埠巨,最終在動(dòng)態(tài)生成的代理類(lèi)中對(duì)用戶方法進(jìn)行攔截)历谍,spring實(shí)現(xiàn)了兩種動(dòng)態(tài)代理:jdk和cglib的,區(qū)別在于:jdk使用java自帶的動(dòng)態(tài)代理功能實(shí)現(xiàn)辣垒,但是只能支持代理繼承于接口的具體類(lèi)望侈;cglib是為了能支持代理非繼承接口的具體類(lèi)(final類(lèi)無(wú)法支持,因?yàn)橥ㄟ^(guò)繼承父類(lèi)實(shí)現(xiàn))乍构,使用了直接生成字節(jié)碼的方式返回class類(lèi)型(據(jù)介紹還比較屌甜无,想了解java字節(jié)碼實(shí)現(xiàn)的,可以看看這塊的源碼哥遮,不夠估計(jì)是native方法,那就得去看jvm虛擬機(jī)c語(yǔ)言源碼了)陵究。關(guān)于動(dòng)態(tài)代理在Spring AOP的實(shí)現(xiàn)方式眠饮,后續(xù)會(huì)單列一章詳細(xì)分析,此處僅簡(jiǎn)單敘述铜邮。

package com.thoughtworks;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Date;

@Component
public class Transaction {

    @Autowired
    private StMapper stMapper;

    @Transactional
    public void transaction() {
        System.out.println(stMapper.getStockCardId(119, 572));
        System.out.println(stMapper.getStockCardId(1, 1));
        System.out.println(stMapper.getCMMEntryHead());
    }
}

下面是StMapping的實(shí)現(xiàn)仪召,該部分是mybatis跟spring整合的代碼,雖然還沒(méi)來(lái)得及細(xì)看源碼松蒜,但是即使是猜扔茅,大概能想到mybatis也只能靠實(shí)現(xiàn)spring的某些插件類(lèi),最終注冊(cè)到spring當(dāng)中去實(shí)現(xiàn)mybatis的orm功能秸苗。如果本文篇幅夠的話召娜,可以把mybatis和spring的整合部分一起看了,不夠的話后面再單列一章惊楼。

package com.thoughtworks;

import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Options;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import org.springframework.stereotype.Repository;

import java.util.List;

@Repository
public interface StMapper {

    @Select("select * from tmp where a = #{a}")
    List<Integer> getStudent(@Param("a") int a);

    @Select("select id from stock_cards where facilityid = ${facilityid} and productid = ${productid}")
    Integer getStockCardId(@Param("facilityid") Integer facilityid, @Param("productid") Integer productid);

    @Select("SELECT * FROM cmm_entries limit 1")
    CMMEntry getCMMEntryHead();
}

ApplicationContext的xml配置玖瘸,數(shù)據(jù)庫(kù)密碼我寫(xiě)在default.properties中秸讹,由于涉及項(xiàng)目信息安全,配置文件就不放置了雅倒,配置文件就是簡(jiǎn)單key=value,每行一對(duì)配置璃诀,spring會(huì)自己去加載配置,然后替換配置中的占位符(比如${openlmis.jdbc.password})蔑匣,這塊我們也會(huì)在后面的源碼中看到spring是如何替換這些占位符的劣欢。

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.1.xsd
                           http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.1.xsd
                           http://www.springframework.org/schema/tx
                           http://www.springframework.org/schema/tx/spring-tx-4.1.xsd">

    <context:annotation-config/>
    <context:spring-configured/>

    <tx:annotation-driven transaction-manager="openLmisTransactionManager"/>

    <bean id="openLmisTransactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource">
            <ref bean="openlmisDataSource"/>
        </property>
    </bean>

    <context:property-placeholder location="default.properties"/>

    <bean id="openlmisDataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
        <property name="driverClass" value="${jdbc.driverClassName}"/>
        <property name="jdbcUrl" value="${openlmis.jdbc.url}"/>
        <property name="user" value="${openlmis.jdbc.username}"/>
        <property name="password" value="${openlmis.jdbc.password}"/>
    </bean>

    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="openlmisDataSource"/>
        <!--property name="typeHandlersPackage" value="org.openlmis.core.repository.typehandler"/-->
    </bean>

    <bean id="myBatisMapperScanner" class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <property name="basePackage" value="com.thoughtworks"/>
        <property name="annotationClass" value="org.springframework.stereotype.Repository"/>
        <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
    </bean>

    <bean id="transaction"
          class="com.thoughtworks.Transaction">
        <!-- 在這里寫(xiě)額外的bean的配置和相關(guān)引用 -->
    </bean>


</beans>

首先,我們從上下文的初始化開(kāi)始裁良,傳入配置文件名稱凿将,該配置文件路徑放在工程的resource目錄下(default.properties也放在resource下面):

ApplicationContext context = new ClassPathXmlApplicationContext("Application-context.xml");

ClassPathXmlApplicationContext首先調(diào)用自己的構(gòu)造函數(shù),將配置文件名稱傳入趴久,隨后繼續(xù)內(nèi)部調(diào)用另外一個(gè)參數(shù)更多的構(gòu)造函數(shù)丸相,我們這里parent為null,之前看到彼棍,ApplicationContext是具有層次性的灭忠,多個(gè)ApplicationContext可以構(gòu)造層次關(guān)系。隨后調(diào)用了最重要的方法refresh方法座硕。

    public ClassPathXmlApplicationContext(String configLocation) throws BeansException {
        this(new String[] {configLocation}, true, null);
    }

    public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent)
            throws BeansException {

        super(parent);
        setConfigLocations(configLocations);
        if (refresh) {
            refresh();
        }
    }   

refresh方法弛作,該方法在AbstractApplicationContext中實(shí)現(xiàn)。synchronized (this.startupShutdownMonitor) 用于保證bean刷新的完整性华匾。

    @Override
    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) {
                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;
            }
        }
    }

Bean加載流程解析

prepareRefresh

prepareRefresh負(fù)責(zé)刷新前的準(zhǔn)備工作映琳,包括環(huán)境信息、配置路徑信息的初始化蜘拉。

obtainFreshBeanFactory

隨后萨西,會(huì)初始化一個(gè)重要對(duì)象--beanFactory,該beanFactory對(duì)象為ConfigurableListableBeanFactory類(lèi)型旭旭。

ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

查看obtainFreshBeanFactory方法谎脯,調(diào)用了AbstractApplicationContext中的兩個(gè)抽象方法refreshBeanFactory和getBeanFactory,在AbstractApplicationContext中持寄,多個(gè)涉及beanFactory的方法都是抽象方法源梭,該beanFactory對(duì)象為ConfigurableListableBeanFactory。

    protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
        refreshBeanFactory();
        ConfigurableListableBeanFactory beanFactory = getBeanFactory();
        if (logger.isDebugEnabled()) {
            logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory);
        }
        return beanFactory;
    }

AbstractApplicationContext的直接子類(lèi)AbstractRefreshableApplicationContext實(shí)現(xiàn)了refreshBeanFactory和getBeanFactory的方法稍味,getBeanFactory里面直接獲取的beanFactory對(duì)象废麻,而負(fù)責(zé)beanFactory對(duì)象初始化方法的實(shí)際上是refreshBeanFactory,在不涉及重建beanFactory的場(chǎng)景中模庐,refreshBeanFactory方法不會(huì)觸發(fā)if分支烛愧。其中createBeanFactory負(fù)責(zé)beanFactory的創(chuàng)建,該beanFactory類(lèi)型為DefaultListableBeanFactory,這個(gè)類(lèi)負(fù)責(zé)代理所有涉及beanFactory的動(dòng)作屑彻,所以這個(gè)類(lèi)相當(dāng)重要验庙。

    @Override
    protected final void refreshBeanFactory() throws BeansException {
        if (hasBeanFactory()) {
            destroyBeans();
            closeBeanFactory();
        }
        try {
            DefaultListableBeanFactory beanFactory = createBeanFactory();
            beanFactory.setSerializationId(getId());
            customizeBeanFactory(beanFactory);
            loadBeanDefinitions(beanFactory);
            synchronized (this.beanFactoryMonitor) {
                this.beanFactory = beanFactory;
            }
        }
        catch (IOException ex) {
            throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
        }
    }
    
    @Override
    public final ConfigurableListableBeanFactory getBeanFactory() {
        synchronized (this.beanFactoryMonitor) {
            if (this.beanFactory == null) {
                throw new IllegalStateException("BeanFactory not initialized or already closed - " +
                        "call 'refresh' before accessing beans via the ApplicationContext");
            }
            return this.beanFactory;
        }
    }

    protected DefaultListableBeanFactory createBeanFactory() {
        return new DefaultListableBeanFactory(getInternalParentBeanFactory());
    }

下圖為DefaultListableBeanFactory的繼承層次:

DefaultListableBeanFactory繼承層次.png

之前已經(jīng)介紹過(guò)的接口不再重復(fù)介紹,只介紹新遇到的接口和類(lèi)型社牲。
接口SingletonBeanRegistry粪薛,負(fù)責(zé)對(duì)單例進(jìn)行注冊(cè),以及獲取單例等跟單例等相關(guān)的方法搏恤。這說(shuō)明beanFactory有專門(mén)處理單例對(duì)象的邏輯违寿。

public interface SingletonBeanRegistry {

    void registerSingleton(String beanName, Object singletonObject);

    Object getSingleton(String beanName);

    boolean containsSingleton(String beanName);

    String[] getSingletonNames();

    int getSingletonCount();
}

接口AliasRegistry,負(fù)責(zé)別名注冊(cè)相關(guān)的方法熟空。這個(gè)接口說(shuō)明beanFactory可以為bean注冊(cè)別名藤巢,可以讓用戶通過(guò)別名訪問(wèn)bean的相關(guān)信息。SimpleAliasRegistry為AliasRegistry的具體類(lèi)息罗,不出意外掂咒,該類(lèi)在后續(xù)肯定是協(xié)助DefaultListableBeanFactory代理執(zhí)行AliasRegistry的這幾個(gè)方法。

public interface AliasRegistry {

    void registerAlias(String name, String alias);

    void removeAlias(String alias);

    boolean isAlias(String beanName);

    String[] getAliases(String name);

}

接口BeanDefinitionRegistry迈喉,負(fù)責(zé)bean定義信息注冊(cè)相關(guān)的方法绍刮。

public interface BeanDefinitionRegistry extends AliasRegistry {

    void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
            throws BeanDefinitionStoreException;

    void removeBeanDefinition(String beanName) throws NoSuchBeanDefinitionException;

    BeanDefinition getBeanDefinition(String beanName) throws NoSuchBeanDefinitionException;

    boolean containsBeanDefinition(String beanName);

    String[] getBeanDefinitionNames();

    int getBeanDefinitionCount();

    boolean isBeanNameInUse(String beanName);

}

DefaultSingletonBeanRegistry,這是個(gè)具體類(lèi)挨摸,繼承自SimpleAliasRegistry和SingletonBeanRegistry孩革。該類(lèi)主要負(fù)責(zé)實(shí)現(xiàn)SingletonBeanRegistry接口中所有的方法。同時(shí)得运,它還實(shí)現(xiàn)了很多其他關(guān)于bean的方法膝蜈,其中包括注冊(cè)bean的依賴關(guān)系,還有bean的銷(xiāo)毀方法熔掺,其中由于包含依賴饱搏,所以多個(gè)方法都是遞歸實(shí)現(xiàn)的。該類(lèi)只負(fù)責(zé)管理和注冊(cè)bean信息置逻,同時(shí)也包含創(chuàng)建bean的功能窍帝。整體類(lèi)功能非常具體且獨(dú)立,所以閱讀起來(lái)也很簡(jiǎn)單诽偷,由于該類(lèi)方法較多,就不貼代碼了疯坤。

public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry {
    ...
}

接口ConfigurableBeanFactory报慕,繼承自HierarchicalBeanFactory, SingletonBeanRegistry,接口中主要是配置beanFactory信息的接口压怠,同時(shí)因?yàn)槔^承自SingletonBeanRegistry眠冈,也包含該接口相關(guān)方法。

public interface ConfigurableBeanFactory extends HierarchicalBeanFactory, SingletonBeanRegistry

抽象類(lèi)FactoryBeanRegistrySupport,繼承自DefaultSingletonBeanRegistry蜗顽。該抽象類(lèi)沒(méi)包含抽象方法布卡,所以僅僅只是不能實(shí)例化。該類(lèi)新增了幾個(gè)方法未包含public方法雇盖,說(shuō)明該類(lèi)僅僅是為了給子類(lèi)提供工具方法忿等,新增方法主要是bean和beanFactory相關(guān)方法。

public abstract class FactoryBeanRegistrySupport extends DefaultSingletonBeanRegistry

AbstractBeanFactory抽象類(lèi)

AbstractBeanFactory抽象類(lèi)繼承自FactoryBeanRegistrySupport崔挖,ConfigurableBeanFactory贸街。該類(lèi)主要實(shí)現(xiàn)了BeanFactory接口中的方法,HierarchicalBeanFactory接口中的方法狸相,以及ConfigurableBeanFactory接口中的方法薛匪。最后,該類(lèi)提供了三個(gè)抽象方法交給子類(lèi)實(shí)現(xiàn)脓鹃。

public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport implements ConfigurableBeanFactory 

BeanFactory接口方法實(shí)現(xiàn)

AbstractBeanFactory抽象類(lèi)實(shí)現(xiàn)了beanFactory的方法逸尖,用來(lái)獲取bean的getBean方法以及一些與bean狀態(tài)和類(lèi)型相關(guān)的方法。比較重要的有g(shù)etBean方法瘸右,getBean方法實(shí)際調(diào)用的是doGetBean方法娇跟,因?yàn)閎ean之間可能存在依賴,所以doGetBean方法中生成bean的時(shí)候是遞歸進(jìn)行的尊浓,真正生成bean對(duì)象的是createBean方法逞频,該方法為抽象方法,由子類(lèi)負(fù)責(zé)實(shí)現(xiàn)栋齿。

protected <T> T doGetBean(
            final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)
            throws BeansException {

        final String beanName = transformedBeanName(name);
        Object bean;

        // Eagerly check singleton cache for manually registered singletons.
        Object sharedInstance = getSingleton(beanName);
        if (sharedInstance != null && args == null) {
            if (logger.isDebugEnabled()) {
                if (isSingletonCurrentlyInCreation(beanName)) {
                    logger.debug("Returning eagerly cached instance of singleton bean '" + beanName +
                            "' that is not fully initialized yet - a consequence of a circular reference");
                }
                else {
                    logger.debug("Returning cached instance of singleton bean '" + beanName + "'");
                }
            }
            bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
        }

        else {
            // Fail if we're already creating this bean instance:
            // We're assumably within a circular reference.
            if (isPrototypeCurrentlyInCreation(beanName)) {
                throw new BeanCurrentlyInCreationException(beanName);
            }

            // Check if bean definition exists in this factory.
            BeanFactory parentBeanFactory = getParentBeanFactory();
            if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
                // Not found -> check parent.
                String nameToLookup = originalBeanName(name);
                if (args != null) {
                    // Delegation to parent with explicit args.
                    return (T) parentBeanFactory.getBean(nameToLookup, args);
                }
                else {
                    // No args -> delegate to standard getBean method.
                    return parentBeanFactory.getBean(nameToLookup, requiredType);
                }
            }

            if (!typeCheckOnly) {
                markBeanAsCreated(beanName);
            }

            try {
                final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
                checkMergedBeanDefinition(mbd, beanName, args);

                // Guarantee initialization of beans that the current bean depends on.
                String[] dependsOn = mbd.getDependsOn();
                if (dependsOn != null) {
                    for (String dependsOnBean : dependsOn) {
                        if (isDependent(beanName, dependsOnBean)) {
                            throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                                    "Circular depends-on relationship between '" + beanName + "' and '" + dependsOnBean + "'");
                        }
                        registerDependentBean(dependsOnBean, beanName);
                        getBean(dependsOnBean);
                    }
                }

                // Create bean instance.
                if (mbd.isSingleton()) {
                    sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {
                        @Override
                        public Object getObject() throws BeansException {
                            try {
                                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);
                }

                else if (mbd.isPrototype()) {
                    // It's a prototype -> create a new instance.
                    Object prototypeInstance = null;
                    try {
                        beforePrototypeCreation(beanName);
                        prototypeInstance = createBean(beanName, mbd, args);
                    }
                    finally {
                        afterPrototypeCreation(beanName);
                    }
                    bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
                }

                else {
                    String scopeName = mbd.getScope();
                    final Scope scope = this.scopes.get(scopeName);
                    if (scope == null) {
                        throw new IllegalStateException("No Scope registered for scope '" + scopeName + "'");
                    }
                    try {
                        Object scopedInstance = scope.get(beanName, new ObjectFactory<Object>() {
                            @Override
                            public Object getObject() throws BeansException {
                                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;
            }
        }

        // Check if required type matches the type of the actual bean instance.
        if (requiredType != null && bean != null && !requiredType.isAssignableFrom(bean.getClass())) {
            try {
                return getTypeConverter().convertIfNecessary(bean, requiredType);
            }
            catch (TypeMismatchException ex) {
                if (logger.isDebugEnabled()) {
                    logger.debug("Failed to convert bean '" + name + "' to required type [" +
                            ClassUtils.getQualifiedName(requiredType) + "]", ex);
                }
                throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
            }
        }
        return (T) bean;
    }

ConfigurableBeanFactory接口實(shí)現(xiàn)

該接口實(shí)現(xiàn)主要包含配置化beanFactory接口的實(shí)現(xiàn)苗胀。

AbstractBeanFactory的抽象方法

protected abstract boolean containsBeanDefinition(String beanName);

protected abstract BeanDefinition getBeanDefinition(String beanName) throws BeansException;

protected abstract Object createBean(String beanName, RootBeanDefinition mbd, Object[] args)
            throws BeanCreationException;
AbstractAutowireCapableBeanFactory抽象類(lèi)

該抽象類(lèi)繼承自AbstractBeanFactory和AutowireCapableBeanFactory,實(shí)現(xiàn)了AbstractBeanFactory的抽象方法creatBean瓦堵,并且實(shí)現(xiàn)了繼承自AutowireCapableBeanFactory的接口基协,提供了bean的創(chuàng)建奕剃,屬性填充授舟,自動(dòng)裝配等功能。

public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory
        implements AutowireCapableBeanFactory 

了解了DefaultListableBeanFactory的繼承層次后艺蝴,可以知道DefaultListableBeanFactory負(fù)責(zé)的功能:bean信息的注冊(cè)惋鸥、bean的獲取杂穷、bean的創(chuàng)建,同時(shí)卦绣,也支持了自動(dòng)裝配等功能耐量,同時(shí)還實(shí)現(xiàn)了插件BeanPostProcessor,初步來(lái)看滤港,這個(gè)beanPostProcessor可以用戶實(shí)現(xiàn)注入到該框架當(dāng)中增強(qiáng)spring的功能廊蜒,還有一些其他功能并未細(xì)看,等到用到時(shí)候再詳細(xì)解讀。

至此山叮,DefaultListableBeanFactory已經(jīng)大致了解清楚著榴。

createBeanFactory調(diào)用結(jié)束后,loadBeanDefinitions(beanFactory)是更重要的方法屁倔,因?yàn)閯?chuàng)建出來(lái)的beanFactory對(duì)象還并未真正進(jìn)行xml配置解析和信息的填充脑又。

    @Override
    protected final void refreshBeanFactory() throws BeansException {
        if (hasBeanFactory()) {
            destroyBeans();
            closeBeanFactory();
        }
        try {
            DefaultListableBeanFactory beanFactory = createBeanFactory();
            beanFactory.setSerializationId(getId());
            customizeBeanFactory(beanFactory);
            loadBeanDefinitions(beanFactory);
            synchronized (this.beanFactoryMonitor) {
                this.beanFactory = beanFactory;
            }
        }
        catch (IOException ex) {
            throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
        }
    }

loadBeanDefinitions方法在AbstractXmlApplicationContext中繼承后實(shí)現(xiàn),該方法進(jìn)一步調(diào)用XmlBeanDefinitionReader來(lái)解析bean信息汰现,解析后填充到beanFactory對(duì)象中挂谍,由于該方法內(nèi)部調(diào)用較為復(fù)雜,涉及相當(dāng)多的對(duì)象瞎饲,需要單列一章介紹口叙。

    @Override
    protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
        // Create a new XmlBeanDefinitionReader for the given BeanFactory.
        XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);

        // Configure the bean definition reader with this context's
        // resource loading environment.
        beanDefinitionReader.setEnvironment(this.getEnvironment());
        beanDefinitionReader.setResourceLoader(this);
        beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));

        // Allow a subclass to provide custom initialization of the reader,
        // then proceed with actually loading the bean definitions.
        initBeanDefinitionReader(beanDefinitionReader);
        loadBeanDefinitions(beanDefinitionReader);
    }

bean定義信息加載完成后,obtainFreshBeanFactory方法執(zhí)行完成嗅战。

prepareBeanFactory(beanFactory)

beanFactory對(duì)象在此方法中妄田,設(shè)置了多個(gè)屬性。

    protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
        // Tell the internal bean factory to use the context's class loader etc.
        beanFactory.setBeanClassLoader(getClassLoader());
        beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
        beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));

        // Configure the bean factory with context callbacks.
        beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
        beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
        beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
        beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
        beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);
        beanFactory.ignoreDependencyInterface(EnvironmentAware.class);

        // BeanFactory interface not registered as resolvable type in a plain factory.
        // MessageSource registered (and found for autowiring) as a bean.
        beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
        beanFactory.registerResolvableDependency(ResourceLoader.class, this);
        beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
        beanFactory.registerResolvableDependency(ApplicationContext.class, this);

        // Detect a LoadTimeWeaver and prepare for weaving, if found.
        if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
            beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
            // Set a temporary ClassLoader for type matching.
            beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
        }

        // Register default environment beans.
        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());
        }
    }

postProcessBeanFactory(beanFactory)

空方法驮捍,需要子類(lèi)繼承實(shí)現(xiàn)才能生效疟呐。

未完待續(xù)。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末东且,一起剝皮案震驚了整個(gè)濱河市启具,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌珊泳,老刑警劉巖鲁冯,帶你破解...
    沈念sama閱讀 212,080評(píng)論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異色查,居然都是意外死亡薯演,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,422評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門(mén)秧了,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)跨扮,“玉大人,你說(shuō)我怎么就攤上這事验毡『獯矗” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 157,630評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵晶通,是天一觀的道長(zhǎng)钧汹。 經(jīng)常有香客問(wèn)我,道長(zhǎng)录择,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,554評(píng)論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮隘竭,結(jié)果婚禮上塘秦,老公的妹妹穿的比我還像新娘。我一直安慰自己动看,他們只是感情好尊剔,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,662評(píng)論 6 386
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著菱皆,像睡著了一般须误。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上仇轻,一...
    開(kāi)封第一講書(shū)人閱讀 49,856評(píng)論 1 290
  • 那天京痢,我揣著相機(jī)與錄音,去河邊找鬼篷店。 笑死祭椰,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的疲陕。 我是一名探鬼主播方淤,決...
    沈念sama閱讀 39,014評(píng)論 3 408
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼蹄殃!你這毒婦竟也來(lái)了携茂?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 37,752評(píng)論 0 268
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤诅岩,失蹤者是張志新(化名)和其女友劉穎讳苦,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體按厘,經(jīng)...
    沈念sama閱讀 44,212評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡医吊,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,541評(píng)論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了逮京。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片卿堂。...
    茶點(diǎn)故事閱讀 38,687評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖懒棉,靈堂內(nèi)的尸體忽然破棺而出草描,到底是詐尸還是另有隱情,我是刑警寧澤策严,帶...
    沈念sama閱讀 34,347評(píng)論 4 331
  • 正文 年R本政府宣布穗慕,位于F島的核電站,受9級(jí)特大地震影響妻导,放射性物質(zhì)發(fā)生泄漏逛绵。R本人自食惡果不足惜怀各,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,973評(píng)論 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望术浪。 院中可真熱鬧瓢对,春花似錦、人聲如沸胰苏。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,777評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)硕并。三九已至法焰,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間倔毙,已是汗流浹背埃仪。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,006評(píng)論 1 266
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留普监,地道東北人贵试。 一個(gè)月前我還...
    沈念sama閱讀 46,406評(píng)論 2 360
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像凯正,于是被迫代替她去往敵國(guó)和親毙玻。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,576評(píng)論 2 349

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

  • 本文是我自己在秋招復(fù)習(xí)時(shí)的讀書(shū)筆記廊散,整理的知識(shí)點(diǎn)桑滩,也是為了防止忘記,尊重勞動(dòng)成果允睹,轉(zhuǎn)載注明出處哦运准!如果你也喜歡,那...
    波波波先森閱讀 12,284評(píng)論 6 86
  • Spring Cloud為開(kāi)發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見(jiàn)模式的工具(例如配置管理缭受,服務(wù)發(fā)現(xiàn)胁澳,斷路器,智...
    卡卡羅2017閱讀 134,633評(píng)論 18 139
  • 1.1 Spring IoC容器和bean簡(jiǎn)介 本章介紹了Spring Framework實(shí)現(xiàn)的控制反轉(zhuǎn)(IoC)...
    起名真是難閱讀 2,578評(píng)論 0 8
  • 塵話桑麻閱讀 804評(píng)論 0 1
  • 曾經(jīng)我以為只要守住心中的一片凈土米者,靜靜地度過(guò)一生即可韭畸。因?yàn)槲乙恢倍己芮宄约合胍氖鞘裁绰悖比A的地方不適合自...
    珞曉閱讀 194評(píng)論 0 1