美文网首页
Spring学习2-Bean的加载过程(IOC实现原理)

Spring学习2-Bean的加载过程(IOC实现原理)

作者: 小鲍比大爷 | 来源:发表于2018-08-23 22:47 被阅读0次

    之前基本理清了ClassPathXmlApplicationContext的继承层次,但一些重点方法和一些重要对象并未触及,本文继续调试和阅读spring源码,希望通过此次学习可以搞明白bean的加载和生成机制。调试的Main方法如下,很简单,实现了一个简单的Transaction对象,使用ClassPathXmlApplicationContext获取transaction对象,调用对象的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对象定义,其中stMapper用到了mybatis,mybatis是比较流行的orm框架,之前也没使用过,由于项目中使用,模仿着写了一个,如果可以的话,顺便将mybatis与spring的整合代码一起看了。trasaction方法上我加上了@Transactional注解,这个注解实现从spring框架中支持了数据库事务,好处在于让程序员避免了在每次提交事务sql时写那些模板代码,通过与mybatis的整合,针对数据库的操作看起来会相当干净,仅仅加上一个注解,就可以轻松实现对事物的控制。这里加上@Transactional注解,是想了解下spring的实现机制,之前看了一点这块的代码,了解到spring的事务本质实际上还是AOP的方式实现(Spring AOP通过动态代理的方式实现,动态代理本质就是动态生成继承接口的类或者继承父类的子类,最终在动态生成的代理类中对用户方法进行拦截),spring实现了两种动态代理:jdk和cglib的,区别在于:jdk使用java自带的动态代理功能实现,但是只能支持代理继承于接口的具体类;cglib是为了能支持代理非继承接口的具体类(final类无法支持,因为通过继承父类实现),使用了直接生成字节码的方式返回class类型(据介绍还比较屌,想了解java字节码实现的,可以看看这块的源码,不够估计是native方法,那就得去看jvm虚拟机c语言源码了)。关于动态代理在Spring AOP的实现方式,后续会单列一章详细分析,此处仅简单叙述。

    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的实现,该部分是mybatis跟spring整合的代码,虽然还没来得及细看源码,但是即使是猜,大概能想到mybatis也只能靠实现spring的某些插件类,最终注册到spring当中去实现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配置,数据库密码我写在default.properties中,由于涉及项目信息安全,配置文件就不放置了,配置文件就是简单key=value,每行一对配置,spring会自己去加载配置,然后替换配置中的占位符(比如${openlmis.jdbc.password}),这块我们也会在后面的源码中看到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">
            <!-- 在这里写额外的bean的配置和相关引用 -->
        </bean>
    
    
    </beans>
    

    首先,我们从上下文的初始化开始,传入配置文件名称,该配置文件路径放在工程的resource目录下(default.properties也放在resource下面):

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

    ClassPathXmlApplicationContext首先调用自己的构造函数,将配置文件名称传入,随后继续内部调用另外一个参数更多的构造函数,我们这里parent为null,之前看到,ApplicationContext是具有层次性的,多个ApplicationContext可以构造层次关系。随后调用了最重要的方法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中实现。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负责刷新前的准备工作,包括环境信息、配置路径信息的初始化。

    obtainFreshBeanFactory

    随后,会初始化一个重要对象--beanFactory,该beanFactory对象为ConfigurableListableBeanFactory类型。

    ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
    

    查看obtainFreshBeanFactory方法,调用了AbstractApplicationContext中的两个抽象方法refreshBeanFactory和getBeanFactory,在AbstractApplicationContext中,多个涉及beanFactory的方法都是抽象方法,该beanFactory对象为ConfigurableListableBeanFactory。

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

    AbstractApplicationContext的直接子类AbstractRefreshableApplicationContext实现了refreshBeanFactory和getBeanFactory的方法,getBeanFactory里面直接获取的beanFactory对象,而负责beanFactory对象初始化方法的实际上是refreshBeanFactory,在不涉及重建beanFactory的场景中,refreshBeanFactory方法不会触发if分支。其中createBeanFactory负责beanFactory的创建,该beanFactory类型为DefaultListableBeanFactory,这个类负责代理所有涉及beanFactory的动作,所以这个类相当重要。

        @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

    之前已经介绍过的接口不再重复介绍,只介绍新遇到的接口和类型。
    接口SingletonBeanRegistry,负责对单例进行注册,以及获取单例等跟单例等相关的方法。这说明beanFactory有专门处理单例对象的逻辑。

    public interface SingletonBeanRegistry {
    
        void registerSingleton(String beanName, Object singletonObject);
    
        Object getSingleton(String beanName);
    
        boolean containsSingleton(String beanName);
    
        String[] getSingletonNames();
    
        int getSingletonCount();
    }
    
    

    接口AliasRegistry,负责别名注册相关的方法。这个接口说明beanFactory可以为bean注册别名,可以让用户通过别名访问bean的相关信息。SimpleAliasRegistry为AliasRegistry的具体类,不出意外,该类在后续肯定是协助DefaultListableBeanFactory代理执行AliasRegistry的这几个方法。

    public interface AliasRegistry {
    
        void registerAlias(String name, String alias);
    
        void removeAlias(String alias);
    
        boolean isAlias(String beanName);
    
        String[] getAliases(String name);
    
    }
    

    接口BeanDefinitionRegistry,负责bean定义信息注册相关的方法。

    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,这是个具体类,继承自SimpleAliasRegistry和SingletonBeanRegistry。该类主要负责实现SingletonBeanRegistry接口中所有的方法。同时,它还实现了很多其他关于bean的方法,其中包括注册bean的依赖关系,还有bean的销毁方法,其中由于包含依赖,所以多个方法都是递归实现的。该类只负责管理和注册bean信息,同时也包含创建bean的功能。整体类功能非常具体且独立,所以阅读起来也很简单,由于该类方法较多,就不贴代码了。

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

    接口ConfigurableBeanFactory,继承自HierarchicalBeanFactory, SingletonBeanRegistry,接口中主要是配置beanFactory信息的接口,同时因为继承自SingletonBeanRegistry,也包含该接口相关方法。

    public interface ConfigurableBeanFactory extends HierarchicalBeanFactory, SingletonBeanRegistry
    

    抽象类FactoryBeanRegistrySupport,继承自DefaultSingletonBeanRegistry。该抽象类没包含抽象方法,所以仅仅只是不能实例化。该类新增了几个方法未包含public方法,说明该类仅仅是为了给子类提供工具方法,新增方法主要是bean和beanFactory相关方法。

    public abstract class FactoryBeanRegistrySupport extends DefaultSingletonBeanRegistry
    

    AbstractBeanFactory抽象类

    AbstractBeanFactory抽象类继承自FactoryBeanRegistrySupport,ConfigurableBeanFactory。该类主要实现了BeanFactory接口中的方法,HierarchicalBeanFactory接口中的方法,以及ConfigurableBeanFactory接口中的方法。最后,该类提供了三个抽象方法交给子类实现。

    public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport implements ConfigurableBeanFactory 
    

    BeanFactory接口方法实现

    AbstractBeanFactory抽象类实现了beanFactory的方法,用来获取bean的getBean方法以及一些与bean状态和类型相关的方法。比较重要的有getBean方法,getBean方法实际调用的是doGetBean方法,因为bean之间可能存在依赖,所以doGetBean方法中生成bean的时候是递归进行的,真正生成bean对象的是createBean方法,该方法为抽象方法,由子类负责实现。

    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接口实现

    该接口实现主要包含配置化beanFactory接口的实现。

    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抽象类

    该抽象类继承自AbstractBeanFactory和AutowireCapableBeanFactory,实现了AbstractBeanFactory的抽象方法creatBean,并且实现了继承自AutowireCapableBeanFactory的接口,提供了bean的创建,属性填充,自动装配等功能。

    public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory
            implements AutowireCapableBeanFactory 
    

    了解了DefaultListableBeanFactory的继承层次后,可以知道DefaultListableBeanFactory负责的功能:bean信息的注册、bean的获取、bean的创建,同时,也支持了自动装配等功能,同时还实现了插件BeanPostProcessor,初步来看,这个beanPostProcessor可以用户实现注入到该框架当中增强spring的功能,还有一些其他功能并未细看,等到用到时候再详细解读。

    至此,DefaultListableBeanFactory已经大致了解清楚。

    createBeanFactory调用结束后,loadBeanDefinitions(beanFactory)是更重要的方法,因为创建出来的beanFactory对象还并未真正进行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中继承后实现,该方法进一步调用XmlBeanDefinitionReader来解析bean信息,解析后填充到beanFactory对象中,由于该方法内部调用较为复杂,涉及相当多的对象,需要单列一章介绍。

        @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方法执行完成。

    prepareBeanFactory(beanFactory)

    beanFactory对象在此方法中,设置了多个属性。

        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)

    空方法,需要子类继承实现才能生效。

    未完待续。

    相关文章

      网友评论

          本文标题:Spring学习2-Bean的加载过程(IOC实现原理)

          本文链接:https://www.haomeiwen.com/subject/bkdviftx.html