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

之前基本理清了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)

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

未完待续。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,607评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,047评论 2 379
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,496评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,405评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,400评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,479评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,883评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,535评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,743评论 1 295
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,544评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,612评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,309评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,881评论 3 306
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,891评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,136评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,783评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,316评论 2 342

推荐阅读更多精彩内容