Spring IOC 容器源码分析笔记 (一)

Spring IOC源码分析笔记

Spring IOC 容器源码分析

IOC 总体来说有两处地方最重要,一个是创建 Bean 容器,一个是初始化 Bean.

1. 最基本的Spring启动

public static void main(String[] args) {
    ApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:application.xml");
}

只需要简单的加载classpath下的application.properties配置文件就可以启动.
需要在pom文件里添加spring依赖.

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>4.3.11.RELEASE</version>
</dependency>

spring-context 会自动将 spring-core、spring-beans、spring-aop、spring-expression 这几个基础 jar 包带进来。

2. ApplicationContext的继承结构和其他IOC容器实现类

偷一张ApplicationContext的继承结构:
ApplicationContext继承结构

在最下层的实现类还有FileSystemXmlApplicationContext和AnnotationConfigApplicationContext

1、FileSystemXmlApplicationContext 的构造函数需要一个 xml 配置文件在系统中的路径,其他和 ClassPathXmlApplicationContext 基本上一样。

2、AnnotationConfigApplicationContext 是基于注解来使用的,它不需要配置文件,采用 java 配置类和各种注解来配置,是比较简单的方式,也是大势所趋吧。

3. 一个QuickStart

1) 创建一个接口和他的实现类:

public interface MessageService {

    String getMessage();

}

public class MessageServiceImpl implements MessageService {

    public String getMessage() {
        return "hello world";
    }

}

2) 接下来, 在resources目录下新建一个xml配置文件.

名称随意,一般习惯叫application.xml 或 application-xxx.xml.

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

    <bean id="messageService" class="com.echi.service.MessageServiceImpl"/>

</beans>

3) 在IOC容器实例完成之后, 从容器中获取bean

public class ApplicationStarter {
    public static void main(String[] args) {
        ApplicationContext applicationContext = 
                new ClassPathXmlApplicationContext("classpath:application.xml");
        System.out.println("context 启动成功");

        // 从IOC容器中获取类型为MessageService的bean
        MessageService messageService = applicationContext.getBean(MessageService.class);
        // 调动bean的方法,确认实例成功
        // 输出 hello world
        System.out.println(messageService.getMessage());
    }
}

这样就引出了主题, 为什么我们可以通过配置的方式就获取到bean.
ApplicationContext 启动过程中,会负责创建实例 Bean,往各个 Bean 中注入依赖等。

4. BeanFactory简介

BeanFactory就是一个生产bean的工厂, 它负责生产和管理各个bean的实例.

1) BeanFactory主要继承结构

BeanFactory主要继承结构

ApplicationContext其实就是一个BeanFactory,

大概翻一下 BeanFactory , ListableBeanFactory , HierarchicalBeanFactory , AuthwireCapableBeanFactory , ApplicationContext 这几个接口的代码.

  • BeanFactory中的方法大多都是getBean().
  • ListableBeanFactory中有返回Map的getBean方法, 这个 Listable 的意思就是,通过这个接口,我们可以获取多个 Bean
  • HierarchicalBeanFactory 内容比较少, 有一个getParentBeanFactory()方法, 也就是说会有父容器和子容器关系.
  • AutowireCapableBeanFactory 比较眼熟autowire这个词, 里面有几个常量, AUTOWIRE_BY_NAME, BY_TYPE之类的, 就是用来自动装配bean的. 但是仔细看上面的继承图, ApplicationContext并没有继承他, 这个不要紧, 在ApplicationContext中有一个getAutowireCapableBeanFactory()方法,没有继承不代表不能组合使用.
  • 还有一个ConfigurableListableBeanFactory , 继承了全部的三个BeanFactory接口.

2) 启动过程分析

先从ClasspathXMLApplicationContext的构造方法开始说起.

// 如果已经有 ApplicationContext 并需要配置成父子关系,那么调用这个构造方法
public ClassPathXmlApplicationContext(ApplicationContext parent) {
    super(parent);
}

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

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

    super(parent);
    // 根据提供的路径,处理成配置文件数组(以分号、逗号、空格、tab、换行符分割)
    setConfigLocations(configLocations);
    if (refresh) {
        // 核心方法
        refresh();
    }
}

接下来就是refresh()方法

这里简单说下为什么是 refresh(),而不是 init() 这种名字的方法。因为 ApplicationContext 建立起来以后,其实我们是可以通过调用 refresh() 这个方法重建的,refresh() 会将原来的 ApplicationContext 销毁,然后再重新执行一次初始化操作。

@Override
public void refresh() throws BeansException, IllegalStateException {
    // 来个锁,不然 refresh() 还没结束,你又来个启动或销毁容器的操作,那不就乱套了嘛
    synchronized (this.startupShutdownMonitor) {

        // 准备工作,记录下容器的启动时间、标记“已启动”状态、处理配置文件中的占位符
        prepareRefresh();

        // 这步比较关键,这步完成后,配置文件就会解析成一个个 Bean 定义,注册到 BeanFactory 中,
        // 当然,这里说的 Bean 还没有初始化,只是配置信息都提取出来了,
        // 注册也只是将这些信息都保存到了注册中心(说到底核心是一个 beanName-> beanDefinition 的 map)
        ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

        // 设置 BeanFactory 的类加载器,添加几个 BeanPostProcessor,手动注册几个特殊的 bean
        // 这块待会会展开说
        prepareBeanFactory(beanFactory);

        try {
            // 【这里需要知道 BeanFactoryPostProcessor 这个知识点,Bean 如果实现了此接口,
            // 那么在容器初始化以后,Spring 会负责调用里面的 postProcessBeanFactory 方法。】

            // 这里是提供给子类的扩展点,到这里的时候,所有的 Bean 都加载、注册完成了,但是都还没有初始化
            // 具体的子类可以在这步的时候添加一些特殊的 BeanFactoryPostProcessor 的实现类或做点什么事
            postProcessBeanFactory(beanFactory);

            // 调用 BeanFactoryPostProcessor 各个实现类的 postProcessBeanFactory(factory) 方法
            invokeBeanFactoryPostProcessors(beanFactory);

            // 注册 BeanPostProcessor 的实现类,注意看和 BeanFactoryPostProcessor 的区别
            // 此接口两个方法: postProcessBeforeInitialization 和 postProcessAfterInitialization
            // 两个方法分别在 Bean 初始化之前和初始化之后得到执行。注意,到这里 Bean 还没初始化
            registerBeanPostProcessors(beanFactory);

            // 初始化当前 ApplicationContext 的 MessageSource,国际化这里就不展开说了,不然没完没了了
            initMessageSource();

            // 初始化当前 ApplicationContext 的事件广播器,这里也不展开了
            initApplicationEventMulticaster();

            // 从方法名就可以知道,典型的模板方法(钩子方法),
            // 具体的子类可以在这里初始化一些特殊的 Bean(在初始化 singleton beans 之前)
            onRefresh();

            // 注册事件监听器,监听器需要实现 ApplicationListener 接口。这也不是我们的重点,过
            registerListeners();

            // 重点,重点,重点
            // 初始化所有的 singleton beans
            //(lazy-init 的除外)
            finishBeanFactoryInitialization(beanFactory);

            // 最后,广播事件,ApplicationContext 初始化完成
            finishRefresh();
        }

        catch (BeansException ex) {
            if (logger.isWarnEnabled()) {
                logger.warn("Exception encountered during context initialization - " +
                        "cancelling refresh attempt: " + ex);
            }

            // Destroy already created singletons to avoid dangling resources.
            // 销毁已经初始化的 singleton 的 Beans,以免有些 bean 会一直占用资源
            destroyBeans();

            // Reset 'active' flag.
            cancelRefresh(ex);

            // 把异常往外抛
            throw ex;
        }

        finally {
            resetCommonCaches();
        }
    }
}

下面,开始一步步肢解这个 refresh() 方法。

创建 Bean 容器前的准备工作

这个比较简单,直接看代码中的几个注释即可。

protected void prepareRefresh() {

    // 记录启动时间,
    // 将 active 属性设置为 true,closed 属性设置为 false,它们都是 AtomicBoolean 类型
    this.startupDate = System.currentTimeMillis();
    this.closed.set(false);
    this.active.set(true);

    if (logger.isInfoEnabled()) {
        logger.info("Refreshing " + this);
    }

    // Initialize any placeholder property sources in the context environment
    initPropertySources();

    // 校验 xml 配置文件
    getEnvironment().validateRequiredProperties();

    this.earlyApplicationEvents = new LinkedHashSet<ApplicationEvent>();
}

创建Bean容器,加载并注册Bean

回到refresh()方法的下一行, obtainFreshBeanFactory()

这个方法是全文最重要的方法之一, 这里会初始化beanFactory, 加载Bean, 注册Bean等等.

当然,这步之后, bean并没有完成初始化.

// AbstractApplicationContext.java
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
    // 关闭旧的beanFactory(如果有), 创建新的beanFactory, 加载bean定义, 注册bean等...
    refreshBeanFactory();

    // 返回刚刚创建的beanFactory
    ConfigurableListableBeanFactory beanFactory = getBeanFactory();
    if (logger.isDebugEnabled()) {
        logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory);
    }
    return beanFactory;
}

// AbstractRefreshableApplicationContext.java 120
@Override
protected final void refreshBeanFactory() throws BeansException {
    // 如果ApplicationContext中已经加载了beanFactory, 销毁所有的bean, 关闭beanFactory
    // 注意, 应用中beanFactory本来就是可以有多个的, 这里不是说应用全局是否有beanFactory, 
    // 而是当前ApplicationContext是否有beanFactory
    if (hasBeanFactory()) {
        destroyBeans();
        closeBeanFactory();
    }
    try {
        // 初始化一个DefaultListableBeanFactory, 为什么用这个等会再说.
        DefaultListableBeanFactory beanFactory = createBeanFactory();

        // 用于beanFactory序列化
        beanFactory.setSerializationId(getId());

        // 下面两个方法很重要
        // 设置beanFactory的两个属性, 是否允许bean覆盖, 是否允许循环引用
        customizeBeanFactory(beanFactory);

        // 加载bean到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);
    }
}

ApplicationContext继承自BeanFactory, 但他不应该被理解为BeanFactory的实现类, 而是其内部有一个实例化的BeanFactory(DefaultListableBeanFactory). 以后所有的beanFactory操作其实是委托给这个实例处理的.

为什么选择实例化DefaultListableBeanFactory, 之前我们看BeanFactory继承结构图的时候,提到一个接口ConfigurableListableBeanFactory, 他继承了BeanFactory下所有的接口, 而这个接口又有一个实现类 DefaultListableBeanFactory, 这个实现类还继承了右边的AbstractAutowireCapableBeanFactory. 所以 DefaultListableBeanFactory基本上是最牛的BeanFactory了,,这也是这边会使用这个类来实例化的原因。

DefaultListableBeanFactory继承结构

如果你想要在程序运行的时候动态往 Spring IOC 容器注册新的 bean,就会使用到这个类。那我们怎么在运行时获得这个实例呢?
之前我们说过 ApplicationContext 接口能获取到 AutowireCapableBeanFactory,就是最右上角那个,然后它向下转型就能得到 DefaultListableBeanFactory 了。

在继续往下之前, 需要了解一个概念,BeanDefinition. 我们说 BeanFactory 是 Bean 容器,那么 Bean 又是什么呢?

这里的BeanDefinition就是我们所说的Spring的Bean, 我们定义的各个Bean其实会转换成BeanDefinition存在于Spring的BeanFactory中.

所以, 如果有人问你Bean是什么的时候, 你要知道Bean在代码层面可以简单的认为是BeanDefinition的实例.

BeanDefinition中保存了我们的Bean信息, 比如这个Bean指向哪个类, 是否是单例, 是否懒加载, 这个Bean依赖了哪些Bean等..

BeanDefinition接口定义

public interface BeanDefinition extends AttributeAccessor, BeanMetadataElement {
    // 我们可以看到, 默认只提供singleton和prototype两种.
    // 那我们还知道request, session, globalSession, application 这几种呢?
    // 他们属于基于 web 的扩展
    String SCOPE_SINGLETON = "singleton";
    String SCOPE_PROTOTYPE = "prototype";

    // 不太重要
    int ROLE_APPLICATION = 0;
    int ROLE_SUPPORT = 1;
    int ROLE_INFRASTRUCTURE = 2;

    // 设置父Bean, 这里涉及到Bean的继承, 不是java继承.
    // 一句话就是: 继承父Bean的配置信息
    void setParentName(String var1);

    // 获取父Bean
    String getParentName();

    // 设置Bean的类名称, 将来要通过反射来生成实例.
    void setBeanClassName(String var1);

    // 获取Bean的类名
    String getBeanClassName();

    // 设置Bean的scope
    void setScope(String var1);

    String getScope();

    // 设置是否懒加载
    void setLazyInit(boolean var1);

    boolean isLazyInit();

    // 设置Bean所依赖的所有Bean, 注意, 这里的依赖不是指属性依赖 (如 @Autowire标记的)
    // 是 depends-on="" 属性设置的值
    void setDependsOn(String... var1);

    // 返回该bean的所有依赖
    String[] getDependsOn();

    // 设置该Bean是否可以注入到其他Bean中, 只对根据类型注入有效
    // 如果根据名称注入, 即使这边设置false也是可以的.
    void setAutowireCandidate(boolean var1);

    // 该Bean是否可以注入到其他Bean中
    boolean isAutowireCandidate();

    // 主要的. 对于同一个接口的多个实现, 如果不指定名字的话,Spring会优先选择设置primary为true的bean
    void setPrimary(boolean var1);

    // 是否是primary的
    boolean isPrimary();

    // 如果该bean采用工厂方法生成, 指定工厂名称.
    // 一句话的意思就是, 有些实例不是用反射创建的, 而是用工厂模式获取的.
    void setFactoryBeanName(String var1);

    // 获取工厂名称
    String getFactoryBeanName();

    // 指定工厂类中的 工厂方法名称
    void setFactoryMethodName(String var1);

    // 获取工厂类中的 工厂方法名称
    String getFactoryMethodName();

    // 构造器参数
    ConstructorArgumentValues getConstructorArgumentValues();

    // Bean中的属性值, 后面给Bean注入属性的时候会说到
    MutablePropertyValues getPropertyValues();

    // 是否singleton
    boolean isSingleton();

    // 是否prototype
    boolean isPrototype();

    // 如果这个Bean是被设置为abstract, 那么不能实例化.
    // 常用作 父Bean 用于继承, 其实也很少用到
    boolean isAbstract();

    int getRole();

    String getDescription();

    String getResourceDescription();

    BeanDefinition getOriginatingBeanDefinition();
}

这个 BeanDefinition 其实已经包含很多的信息了,暂时不清楚所有的方法对应什么东西没关系,希望看完本文后读者可以彻底搞清楚里面的所有东西。
这里接口虽然那么多,但是没有类似 getInstance() 这种方法来获取我们定义的类的实例,真正的我们定义的类生成的实例到哪里去了呢?别着急,这个要很后面才能讲到。

有了BeanDefinition的概念后, 我们继续往下看refreshBeanFactory中的内容.

customizeBeanFactory(beanFactory);
loadBeanDefinitions(beanFactory);

虽然只有两个方法,但路还很长啊。。。

customizeBeanFactory
customizeBeanFactory(beanFactory)比较简单, 就是配置是否允许BeanDefinition覆盖,是否允许循环引用.

protected void customizeBeanFactory(DefaultListableBeanFactory beanFactory) {
    if (this.allowBeanDefinitionOverriding != null) {
        // 是否允许Bean定义覆盖
        beanFactory.setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
    }
    if (this.allowCircularReferences != null) {
        // 是否允许Bean间循环引用
        beanFactory.setAllowCircularReferences(this.allowCircularReferences);
    }
}

BeanDefinition覆盖的问题可能好多开发者会碰到这个坑, 就是在配置文件中定义bean的时候,使用了相同的id或name, 默认情况下, allowBeanDefinitionOverriding属性为null, 如果同一配置文件中重复了, 会抛错, 但是如果不是同一配置文件中, 会发生覆盖.

循环引用也很好理解: A依赖B, B依赖A. 或A依赖B, B依赖C, C依赖A.

默认情况下, Spring允许依赖循环, 当然如果你在A的构造器中依赖B, B的构造器中依赖A是不行的.

加载Bean: loadBeanDefinitions

接下来是最重要的loadBeanDefinition(beanFactory)方法了, 这个方法将根据配置, 加载各个Bean, 然后放入BeanFactory中.

读取配置的操作在XmlBeanDefinitionReader中, 其负责加载配置, 解析.

// AbstractXmlApplicationContext.java 80

/** 我们可以看到,此方法将通过一个 XmlBeanDefinitionReader 实例来加载各个 Bean。*/
@Override
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) 
            throws BeansException, IOException {
    // 给这个BeanFactory实例化一个XmlBeanDefinitionReader
    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));

    // 初始化BeanDefinitionReader, 其实是提供给子类覆写的.
    // 我看了一下,没有类覆写这个方法,我们姑且当做不重要吧
    initBeanDefinitionReader(beanDefinitionReader);

    // 重点来了,继续往下
    loadBeanDefinitions(beanDefinitionReader);
}

接下来用刚刚实例化的XMLBeanDefinitionReader来加载Xml配置,

// AbstractXmlApplicationContext.java 120
protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) 
            throws BeansException, IOException {
    Resource[] configResources = getConfigResources();
    if (configResources != null) {
        // 进入
        reader.loadBeanDefinitions(configResources);
    }
    String[] configLocations = getConfigLocations();
    if (configLocations != null) {
        // 2
        reader.loadBeanDefinitions(configLocations);
    }
}

// 上面虽然有两个分支,不过第二个分支很快通过解析路径转换为 Resource 以后也会进到这里
@Override
public int loadBeanDefinitions(Resource... resources) throws BeanDefinitionStoreException {
    Assert.notNull(resources, "Resource array must not be null");
    int counter = 0;
    // 这里是一个for循环, 也就是每一个文件是一个resource
    for (Resource resource : resources) {
        // 进入
        counter += loadBeanDefinitions(resource);
    }
    //最后返回 counter,表示总共加载了多少的 BeanDefinition
    return counter;
}

// XMLBeanDefinitionReader.java 302
@Override
public int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException {
    return loadBeanDefinitions(new EncodedResource(resource));
}

// XMLBeanDefinitionReader.java 314
public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException {
    Assert.notNull(encodedResource, "EncodedResource must not be null");
    if (logger.isInfoEnabled()) {
        logger.info("Loading XML bean definitions from " + encodedResource.getResource());
    }

    // 用一个ThreadLocal来存放配置文件资源
    Set<EncodedResource> currentResources = this.resourcesCurrentlyBeingLoaded.get();
    if (currentResources == null) {
        currentResources = new HashSet<EncodedResource>(4);
        this.resourcesCurrentlyBeingLoaded.set(currentResources);
    }
    if (!currentResources.add(encodedResource)) {
        throw new BeanDefinitionStoreException(
                "Detected cyclic loading of " + encodedResource + " - check your import definitions!");
    }
    try {
        InputStream inputStream = encodedResource.getResource().getInputStream();
        try {
            InputSource inputSource = new InputSource(inputStream);
            if (encodedResource.getEncoding() != null) {
                inputSource.setEncoding(encodedResource.getEncoding());
            }
            // 核心部分是这里,往下面看
            return doLoadBeanDefinitions(inputSource, encodedResource.getResource());
        }
        finally {
            inputStream.close();
        }
    }
    catch (IOException ex) {
        throw new BeanDefinitionStoreException(
                "IOException parsing XML document from " + encodedResource.getResource(), ex);
    }
    finally {
        currentResources.remove(encodedResource);
        if (currentResources.isEmpty()) {
            this.resourcesCurrentlyBeingLoaded.remove();
        }
    }
}

protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
        throws BeanDefinitionStoreException {
    try {
        // 将xml转成Document对象
        Document doc = doLoadDocument(inputSource, resource);
        // 进入
        return registerBeanDefinitions(doc, resource);
    }
    catch (BeanDefinitionStoreException ex) {
        throw ex;
    }
    ...
}


public int registerBeanDefinitions(Document doc, Resource resource) 
            throws BeanDefinitionStoreException {
    BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
    int countBefore = getRegistry().getBeanDefinitionCount();
    // 进入
    documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
    // 返回从当前配置文件加载了多少数量的 Bean
    return getRegistry().getBeanDefinitionCount() - countBefore;
}

// DefaultBeanDefinitionDocumentReader.java 90
@Override
public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
    this.readerContext = readerContext;
    logger.debug("Loading bean definitions");
    Element root = doc.getDocumentElement();
    doRegisterBeanDefinitions(root);
}

经过漫长的链路,一个配置文件终于转换为一颗 DOM 树了,注意,这里指的是其中一个配置文件,不是所有的,读者可以看到上面有个 for 循环的。下面开始从根节点开始解析:

// DefaultBeanDefinitionDocumentReader.java 116
protected void doRegisterBeanDefinitions(Element root) {
    // BeanDefinitionParserDelegate 负责解析Bean定义
    // 这里为什么要定义一个 parent? 看到后面就知道了,是递归问题,
    // 因为 <beans /> 内部是可以定义 <beans /> 的,所以这个方法的 root 其实不一定就是 xml 的根节点,
    // 也可以是嵌套在里面的 <beans /> 节点,从源码分析的角度,我们当做根节点就好了
    BeanDefinitionParserDelegate parent = this.delegate;
    this.delegate = createDelegate(getReaderContext(), root, parent);

    if (this.delegate.isDefaultNamespace(root)) {
        // 这块说的是根节点 <bean ... profile="dev"> 中的profile是否是当前环境需要的
        // 如果当前环境配置的profile不包含此profile, 就直接return了, 不对此<beans /> 解析.
        String profileSpec = root.getAttribute(PROFILE_ATTRIBUTE);
        if (StringUtils.hasText(profileSpec)) {
            String[] specifiedProfiles = StringUtils.tokenizeToStringArray(
                    profileSpec, BeanDefinitionParserDelegate.MULTI_VALUE_ATTRIBUTE_DELIMITERS);
            if (!getReaderContext().getEnvironment().acceptsProfiles(specifiedProfiles)) {
                if (logger.isInfoEnabled()) {
                    logger.info("Skipped XML bean definition file due to specified profiles [" + 
                        profileSpec + "] not matching: " + getReaderContext().getResource());
                }
                return;
            }
        }
    }

    // 钩子
    preProcessXml(root);
    // 进入
    parseBeanDefinitions(root, this.delegate);
    // 钩子
    postProcessXml(root);

    this.delegate = parent;
}

preProcessXml(root) 和 postProcessXml(root) 是给子类用的钩子方法,鉴于没有被使用到,也不是我们的重点,我们直接跳过。

这里涉及到了 profile 的问题,对于不了解的读者,我在附录中对 profile 做了简单的解释,读者可以参考一下。

profile就是多环境配置中, application-xxx.properties 中配置的环境.
即, 如果配置了 <bean .. profile=”dev” /> 那么只有在dev环境生效时, 才会加载这个bean

接下来,看核心解析方法 parseBeanDefinitions(root, this.delegate) :


protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
    // default namespace 涉及到的就四个标签 <import />、<alias />、<bean /> 和 <beans />,
    // 其他的属于 custom 的
    if (delegate.isDefaultNamespace(root)) {
        NodeList nl = root.getChildNodes();
        for (int i = 0; i < nl.getLength(); i++) {
            Node node = nl.item(i);
            if (node instanceof Element) {
                Element ele = (Element) node;
                if (delegate.isDefaultNamespace(ele)) {
                    // 解析default namespace下面的元素
                    parseDefaultElement(ele, delegate);
                }
                else {
                    // 解析其他 namespace 下面的元素
                    delegate.parseCustomElement(ele);
                }
            }
        }
    }
    else {
        delegate.parseCustomElement(root);
    }
}

从上面的代码,我们可以看到,对于每个配置来说,分别进入到 parseDefaultElement(ele, delegate);delegate.parseCustomElement(ele); 这两个分支了。

parseDefaultElement(ele, delegate);解析的节点是 <import />, <alias />, <beans />, <bean /> 这几个.

private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
    // 处理 <import />
    if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) {
        importBeanDefinitionResource(ele);
    }
    // 处理<alias />
    // <alias name="fromName" alias="toName"/>
    else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) {
        processAliasRegistration(ele);
    }
    // 处理 <bean /> ,这也算是我们的重点吧
    else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) {
        processBeanDefinition(ele, delegate);
    }
    // 处理 <beans />
    else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {
        // 如果碰到的是嵌套的 <beans /> 标签,需要递归
        doRegisterBeanDefinitions(ele);
    }
}

我们重点说标签.

processBeanDefinition 解析 bean 标签

// DefaultBeanDefinitionDocumentReader 298
protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
    // 将节点中的信息提取出来, 封装成一个BeanDefinitionHolder
    BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);

    // 下面几行先跳过
    if (bdHolder != null) {
        bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
        try {
            // Register the final decorated instance.
            BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, 
                getReaderContext().getRegistry());
        }
        catch (BeanDefinitionStoreException ex) {
            getReaderContext().error("Failed to register bean definition with name '" +
                    bdHolder.getBeanName() + "'", ele, ex);
        }
        // Send registration event.
        getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
    }
}

继续往下看怎么解析之前,我们先看下 标签中可以定义哪些属性:

Property  
class 类的全限定名
name 可指定 id、name(用逗号、分号、空格分隔)
scope 作用域
constructor arguments 指定构造参数
properties 设置属性的值
autowiring mode no(默认值)、byName、byType、 constructor
lazy-initialization mode 是否懒加载(如果被非懒加载的bean依赖了那么其实也就不能懒加载了)
initialization method bean 属性设置完成后,会调用这个方法
destruction method bean 销毁后的回调方法

简单地说就是像下面这样子:

<bean id="exampleBean" name="name1, name2, name3" class="com.javadoop.ExampleBean"
      scope="singleton" lazy-init="true" init-method="init" destroy-method="cleanup">

    <!-- 可以用下面三种形式指定构造参数 -->
    <constructor-arg type="int" value="7500000"/>
    <constructor-arg name="years" value="7500000"/>
    <constructor-arg index="0" value="7500000"/>

    <!-- property 的几种情况 -->
    <property name="beanOne">
        <ref bean="anotherExampleBean"/>
    </property>
    <property name="beanTwo" ref="yetAnotherBean"/>
    <property name="integerProperty" value="1"/>
</bean>

当然,除了上面举例出来的这些,还有 factory-bean、factory-method、 这几个

有了以上这些知识以后,我们再继续往里看怎么解析 bean 元素,是怎么转换到 BeanDefinitionHolder 的。

// BeanDefinitionParserDelegate.java 428
public BeanDefinitionHolder parseBeanDefinitionElement(Element ele) {
    return parseBeanDefinitionElement(ele, null);
}

public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, BeanDefinition containingBean) {
    String id = ele.getAttribute(ID_ATTRIBUTE);
    String nameAttr = ele.getAttribute(NAME_ATTRIBUTE);

    // 将name属性的定义按照 "逗号,分好,空格"切分, 形成一个别名列表数组
    // 如果没有定义name, 就为空.
    List<String> aliases = new ArrayList<String>();
    if (StringUtils.hasLength(nameAttr)) {
        String[] nameArr = StringUtils.tokenizeToStringArray(nameAttr, 
            MULTI_VALUE_ATTRIBUTE_DELIMITERS);
        aliases.addAll(Arrays.asList(nameArr));
    }

    String beanName = id;
    // 如果没有指定id, 那么就用别名列表的第一个名字作为beanName
    if (!StringUtils.hasText(beanName) && !aliases.isEmpty()) {
        beanName = aliases.remove(0);
        if (logger.isDebugEnabled()) {
            logger.debug("No XML 'id' specified - using '" + beanName +
                    "' as bean name and " + aliases + " as aliases");
        }
    }

    if (containingBean == null) {
        checkNameUniqueness(beanName, aliases, ele);
    }

    // 根据 <bean ..>...</bean> 中的配置创建 BeanDefinition, 然后把配置中的信息都设置到实例中.
    // 细节后面再说, 先知道这行过后就产生了一个BeanDefinition.
    AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean);

    // 到这里, 整个<bean />标签就算解析结束了, 一个BeanDefinition也形成了.
    if (beanDefinition != null) {
        // 如果没有设置id和name的话, 就会进入下面这块代码
        if (!StringUtils.hasText(beanName)) {
            try {
                // 按照我们的思路,这里 containingBean 是 null 的
                if (containingBean != null) {
                    beanName = BeanDefinitionReaderUtils.generateBeanName(
                            beanDefinition, this.readerContext.getRegistry(), true);
                }
                else {
                    // 如果我们不定义 id 和 name,那么我们引言里的那个例子:
                    //   1. beanName 为:com.javadoop.example.MessageServiceImpl#0
                    //   2. beanClassName 为:com.javadoop.example.MessageServiceImpl
                    beanName = this.readerContext.generateBeanName(beanDefinition);

                    String beanClassName = beanDefinition.getBeanClassName();
                    if (beanClassName != null && beanName.startsWith(beanClassName)  && 
                            beanName.length() > beanClassName.length() &&
                            !this.readerContext.getRegistry().isBeanNameInUse(beanClassName)) {
                        // 把beanClassName设置成别名
                        aliases.add(beanClassName);
                    }
                }
                if (logger.isDebugEnabled()) {
                    logger.debug("Neither XML 'id' nor 'name' specified - " +
                            "using generated bean name [" + beanName + "]");
                }
            }
            catch (Exception ex) {
                error(ex.getMessage(), ele);
                return null;
            }
        }
        String[] aliasesArray = StringUtils.toStringArray(aliases);
        // 返回 BeanDefinitionHolder
        return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray);
    }

    return null;
}

然后,我们再看看怎么根据配置创建 BeanDefinition 实例的:

public AbstractBeanDefinition parseBeanDefinitionElement(
        Element ele, String beanName, BeanDefinition containingBean) {

    this.parseState.push(new BeanEntry(beanName));

    String className = null;
    if (ele.hasAttribute(CLASS_ATTRIBUTE)) {
        className = ele.getAttribute(CLASS_ATTRIBUTE).trim();
    }

    try {
        String parent = null;
        if (ele.hasAttribute(PARENT_ATTRIBUTE)) {
            parent = ele.getAttribute(PARENT_ATTRIBUTE);
        }
        // 创建 BeanDefinition,然后设置类信息而已,很简单,就不贴代码了
        AbstractBeanDefinition bd = createBeanDefinition(className, parent);

        // 设置 BeanDefinition 的一堆属性,这些属性定义在 AbstractBeanDefinition 中
        parseBeanDefinitionAttributes(ele, beanName, containingBean, bd);
        bd.setDescription(DomUtils.getChildElementValueByTagName(ele, DESCRIPTION_ELEMENT));

        // 解析 <meta />
        parseMetaElements(ele, bd);
        // 解析 <lookup-method />
        parseLookupOverrideSubElements(ele, bd.getMethodOverrides());
        // 解析 <replace-method />
        parseReplacedMethodSubElements(ele, bd.getMethodOverrides());

        // 解析 <cnostructor-arg />
        parseConstructorArgElements(ele, bd);
        // 解析 <property />
        parsePropertyElements(ele, bd);
        // 解析 <qualifier />
        parseQualifierElements(ele, bd);

        bd.setResource(this.readerContext.getResource());
        bd.setSource(extractSource(ele));

        return bd;
    }
    catch (ClassNotFoundException ex) {
        error("Bean class [" + className + "] not found", ele, ex);
    }
    catch (NoClassDefFoundError err) {
        error("Class that bean class [" + className + "] depends on not found", ele, err);
    }
    catch (Throwable ex) {
        error("Unexpected failure during bean definition parsing", ele, ex);
    }
    finally {
        this.parseState.pop();
    }

    return null;
}

到这里, 我们已经根据配置创建了一个BeanDefinitionHodler实例. 注意, 是一个.

我们回到解析 的入口方法

protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
    // 上面一大串就是创建了BeanDefinitionHolder
    BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
    if (bdHolder != null) {
        // 如果有自定义属性的话, 先进行相关解析, 先忽略
        bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
        try {
            // 我们把这一步叫做 注册Bean吧
            BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
        }
        catch (BeanDefinitionStoreException ex) {
            getReaderContext().error("Failed to register bean definition with name '" +
                    bdHolder.getBeanName() + "'", ele, ex);
        }
        // 注册完成后,发送事件,本文不展开说这个
        getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
    }
}

我们已经根据 生成了一个BeanDefinitionHolder, 这个实例里也就BeanDefinition和他的beanName, aliases 的信息. 注意,我们的关注点始终在BeanDefinition上.

public class BeanDefinitionHolder implements BeanMetadataElement {

    private final BeanDefinition beanDefinition;

    private final String beanName;

    private final String[] aliases;
}

然后我们准备注册这个BeanDefinition, 最后, 把这个注册时间发送出去

下面, 我们说说注册bean吧.

// BeanDefinitionReaderUtils 
public static void registerBeanDefinition(
        BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)
        throws BeanDefinitionStoreException {

    String beanName = definitionHolder.getBeanName();
    // 注册这个bean
    registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());

    // 如果有别名的话, 也要把别名注册一下, 不然根据别名找不到bean了
    String[] aliases = definitionHolder.getAliases();
    if (aliases != null) {
        for (String alias : aliases) {
            // alias -> beanName 保存它们的别名信息,这个很简单,用一个 map 保存一下就可以了,
            // 获取的时候, 会将alias转成 beanName, 然后再查找
            registry.registerAlias(beanName, alias);
        }
    }
}

别名注册先放一边,毕竟他很简单. 我们先看看怎么注册Bean

// DefaultListableBeanFactory.java 793
@Override
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
        throws BeanDefinitionStoreException {

    Assert.hasText(beanName, "Bean name must not be empty");
    Assert.notNull(beanDefinition, "BeanDefinition must not be null");

    if (beanDefinition instanceof AbstractBeanDefinition) {
        try {
            ((AbstractBeanDefinition) beanDefinition).validate();
        }
        catch (BeanDefinitionValidationException ex) {
            throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
                    "Validation of bean definition failed", ex);
        }
    }

    // old? 还记得 “允许 bean 覆盖” 这个配置吗?allowBeanDefinitionOverriding
    BeanDefinition oldBeanDefinition;

    // 之后会看到, 所有的Bean注册后会放入到这个BeanDefinitionMap中
    oldBeanDefinition = this.beanDefinitionMap.get(beanName);

    // 处理重复名称 bean定义的情况.
    if (oldBeanDefinition != null) {
        if (!isAllowBeanDefinitionOverriding()) {
            // 如果不允许覆盖的话, 抛异常
            throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
                    "Cannot register bean definition [" + beanDefinition + "] for bean '" + beanName +
                    "': There is already [" + oldBeanDefinition + "] bound.");
        }
        else if (oldBeanDefinition.getRole() < beanDefinition.getRole()) {
            // 用框架  的bean覆盖用户自定义的bean
            if (this.logger.isWarnEnabled()) {
                this.logger.warn("Overriding user-defined bean definition for bean '" + beanName +
                        "' with a framework-generated bean definition: replacing [" +
                        oldBeanDefinition + "] with [" + beanDefinition + "]");
            }
        }
        else if (!beanDefinition.equals(oldBeanDefinition)) {
            // 用新的bean覆盖旧的bean
            if (this.logger.isInfoEnabled()) {
                this.logger.info("Overriding bean definition for bean '" + beanName +
                        "' with a different definition: replacing [" + oldBeanDefinition +
                        "] with [" + beanDefinition + "]");
            }
        }
        else {
            if (this.logger.isDebugEnabled()) {
                this.logger.debug("Overriding bean definition for bean '" + beanName +
                        "' with an equivalent definition: replacing [" + oldBeanDefinition +
                        "] with [" + beanDefinition + "]");
            }
        }
        // 覆盖beanDefinition
        this.beanDefinitionMap.put(beanName, beanDefinition);
    }
    else {
        // 判断有没有其他bean开始初始化了
        // 注意, "注册bean" 这个动作结束,bean依赖还没有初始化, 我们后面会有大篇幅说初始化过程
        // 在spring容器启动的最后, 会 预初始化 所有的singleton beans
        if (hasBeanCreationStarted()) {
            // Cannot modify startup-time collection elements anymore (for stable iteration)
            synchronized (this.beanDefinitionMap) {
                this.beanDefinitionMap.put(beanName, beanDefinition);
                List<String> updatedDefinitions = new ArrayList<String>(this.beanDefinitionNames.size() + 1);
                updatedDefinitions.addAll(this.beanDefinitionNames);
                updatedDefinitions.add(beanName);
                this.beanDefinitionNames = updatedDefinitions;
                if (this.manualSingletonNames.contains(beanName)) {
                    Set<String> updatedSingletons = new LinkedHashSet<String>(this.manualSingletonNames);
                    updatedSingletons.remove(beanName);
                    this.manualSingletonNames = updatedSingletons;
                }
            }
        }
        else {
            // 正常应该是进入这个分支
            // 将BeanDefinition放入这个map中, 这个map保存了所有的BeanDefinition
            this.beanDefinitionMap.put(beanName, beanDefinition);
            // 这是个ArrayList, 会按照bean配置的顺序保存每一个注册的bean的名字
            this.beanDefinitionNames.add(beanName);
            // 这是个LinkedHashSet, 代表的是手动注册 singleton bean
            // 注意这里是remove方法, 到这里的bean当然不是手动注册的.
            // 手动指的是通过以下方法注册的bean:
            //      registerSingleton(String beanName, Object singletonObject)
            // 这不是重点, Spring会在后面"手动"注册一些bean
            // 如"environment", "systemProperties"等bean, 我们自己也可以在运行时注册bean到容器中.
            this.manualSingletonNames.remove(beanName);
        }
        // 这个不重要, 初始化的时候会用到. 不用管它
        this.frozenBeanDefinitionNames = null;
    }

    if (oldBeanDefinition != null || containsSingleton(beanName)) {
        resetBeanDefinition(beanName);
    }
}

总结一下, 到这里已经初始化了Bean容器, 配置也转换成了一个个BeanDefinition, 然后注册BeanDefinition到注册中心, 并且发送了注册事件.


一直到上面, 东西都还算简单, 只是比较繁琐.

bean容器实例化完成之后

说到这里, 我们回到refresh方法, 是的,我们才刚刚说完obtainFreshBeanFactory方法.

@Override
public void refresh() throws BeansException, IllegalStateException {
   // 来个锁,不然 refresh() 还没结束,你又来个启动或销毁容器的操作,那不就乱套了嘛
   synchronized (this.startupShutdownMonitor) {

      // 准备工作,记录下容器的启动时间、标记“已启动”状态、处理配置文件中的占位符
      prepareRefresh();

      // 这步比较关键,这步完成后,配置文件就会解析成一个个 Bean 定义,注册到 BeanFactory 中,
      // 当然,这里说的 Bean 还没有初始化,只是配置信息都提取出来了,
      // 注册也只是将这些信息都保存到了注册中心(说到底核心是一个 beanName-> beanDefinition 的 map)
      ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

      // 设置 BeanFactory 的类加载器,添加几个 BeanPostProcessor,手动注册几个特殊的 bean
      // 这块待会会展开说
      prepareBeanFactory(beanFactory);

      try {
         // 【这里需要知道 BeanFactoryPostProcessor 这个知识点,Bean 如果实现了此接口,
         // 那么在容器初始化以后,Spring 会负责调用里面的 postProcessBeanFactory 方法。】

         // 这里是提供给子类的扩展点,到这里的时候,所有的 Bean 都加载、注册完成了,但是都还没有初始化
         // 具体的子类可以在这步的时候添加一些特殊的 BeanFactoryPostProcessor 的实现类或做点什么事
         postProcessBeanFactory(beanFactory);
         // 调用 BeanFactoryPostProcessor 各个实现类的 postProcessBeanFactory(factory) 回调方法
         invokeBeanFactoryPostProcessors(beanFactory);          



         // 注册 BeanPostProcessor 的实现类,注意看和 BeanFactoryPostProcessor 的区别
         // 此接口两个方法: postProcessBeforeInitialization 和 postProcessAfterInitialization
         // 两个方法分别在 Bean 初始化之前和初始化之后得到执行。这里仅仅是注册,之后会看到回调这两方法的时机
         registerBeanPostProcessors(beanFactory);

         // 初始化当前 ApplicationContext 的 MessageSource,国际化这里就不展开说了,不然没完没了了
         initMessageSource();

         // 初始化当前 ApplicationContext 的事件广播器,这里也不展开了
         initApplicationEventMulticaster();

         // 从方法名就可以知道,典型的模板方法(钩子方法),不展开说
         // 具体的子类可以在这里初始化一些特殊的 Bean(在初始化 singleton beans 之前)
         onRefresh();

         // 注册事件监听器,监听器需要实现 ApplicationListener 接口。这也不是我们的重点,过
         registerListeners();

         // 重点,重点,重点
         // 初始化所有的 singleton beans
         //(lazy-init 的除外)
         finishBeanFactoryInitialization(beanFactory);

         // 最后,广播事件,ApplicationContext 初始化完成,不展开
         finishRefresh();
      }

      catch (BeansException ex) {
         if (logger.isWarnEnabled()) {
            logger.warn("Exception encountered during context initialization - " +
                  "cancelling refresh attempt: " + ex);
         }

         // Destroy already created singletons to avoid dangling resources.
         // 销毁已经初始化的 singleton 的 Beans,以免有些 bean 会一直占用资源
         destroyBeans();

         // Reset 'active' flag.
         cancelRefresh(ex);

         // 把异常往外抛
         throw ex;
      }

      finally {
         // Reset common introspection caches in Spring's core, since we
         // might not ever need metadata for singleton beans anymore...
         resetCommonCaches();
      }
   }
}

准备bean容器: prepareBeanFactory

之前我们说过, Spring把我们在xml配置的bean都注册之后,或”手动”注册一些特殊的bean.

这里简单介绍一下prepareBeanFactory(factory)方法.

protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
    // 设置beanFactory的类加载器, 我们知道beanFactory需要加载类, 也就需要类加载器
    // 这里设置当前Application类的类加载器
    beanFactory.setBeanClassLoader(getClassLoader());

    // 设置BeanExpressResolver
    beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
    beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));

    // 添加了一个BeanPostProcessor, 这个processor比较简单:
    // 实现了 Aware 接口的beans 在初始化的时候, 这个processor负责回调
    // 这个我们很常用, 比如为了获取ApplicationContext而 implements ApplicationContextAware
    // 注意, 他不光会回调 ApplicationContextAware,
    //      还会回调 EnvironmentAware, ResourceLoaderAware等, 看下源码就知道了
    beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));

    // 下面几行的意思是, 如果某个bean依赖以下几个接口的实现类, 在自动装配的时候会忽略他们.
    // Spring会通过其他方式来处理这些依赖.
    beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
    beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
    beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
    beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
    beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
    beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);

    // 下面几行就是为几个特殊的bean赋值. 如果有bean依赖了以下几个, 会注入这边相应的值
    // 之前我们说过, "当前ApplicationContext持有一个BeanFactory", 这里解释了第一行
    // ApplicationContext还继承了ResourceLoader, ApplicationEventPublisher, MessageSource
    // 所以对于这几个依赖, 可以赋值为this, 注意,这里的this是一个 ApplicationContext
    // 那这里为什么没看到MessageSource赋值呢? 那是因为MessageSource被注册成了一个普通的bean
    beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
    beanFactory.registerResolvableDependency(ResourceLoader.class, this);
    beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
    beanFactory.registerResolvableDependency(ApplicationContext.class, this);

    // 这个BeanPostProcessor也很简单, 在Bean实例化之后, 如果是ApplicationListener的子类
    // 那么将其添加到listener列表中, 可以理解为: 注册事件监听器
    beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));

    // 这里涉及到的特殊bean, 名为 loadTimeWeaver, 这不是重点, 忽略他
    // tips: ltw是AspectJ的概念, 指的是运行期进行织入, 和Spring的AOP不同

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

    // 从下面几行我们可以看到, Spring往往看起来很智能, 就是因为他会帮我们默认注册一些有用的bean
    // 当然我们也可以选择覆盖

    // 如果我们没有定义"environment"这个bean, 那么Spring会手动注册一个
    if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {
        beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());
    }

    // 如果我们没有定义"systemProperties"这个bean, 那么Spring会手动注册一个
    if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {
        beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());
    }

    // 如果我们没有定义"systemEnvironment"这个bean, 那么Spring会手动注册一个
    if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {
        beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());
    }
}

在上面这块代码中, Spring对一些特殊的bean做了处理, 暂时看不懂也没关系.

初始化所有的Singleton bean

我们的重点是 finishBeanFactoryInitialization(beanFactory); 这个方法, 这里会负责初始化所有的singleton bean

注意,在后面会用初始化预初始化来代表这个阶段, Spring会在这个阶段完成所有Singleton bean的实例化.

我们先总结一下, 到目前为止, BeanFactory已经创建完成, 并且所有实现了BeanFactoryPostProcessor接口的bean已经初始化, 并且postProcessBeanFactory(factory)方法已经得到回调. 而且Spring也手动注册了一些特殊的Bean, 如 environment, systemProperties等.

剩下的就是初始化 singleton bean 了, 我们知道他是单例的, 如果没有懒加载, spring会在接下来初始化所有的singleton bean.

// AbstractApplicationContext.java 834

// 初始化所有剩余的singleton beans
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
    // 首先, 初始化名字为 convertionService的bean, conversionService相关会贴在紧跟着这块代码后
    if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) &&
            beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {

        //什么,看代码这里没有初始化 Bean 啊!
        // 初始化的动作包装在 beanFactory.getBean()中, 这里先不说细节
        beanFactory.setConversionService(
                beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));
    }

    // Register a default embedded value resolver if no bean post-processor
    // (such as a PropertyPlaceholderConfigurer bean) registered any before:
    // at this point, primarily for resolution in annotation attribute values.
    if (!beanFactory.hasEmbeddedValueResolver()) {
        beanFactory.addEmbeddedValueResolver(new StringValueResolver() {
            @Override
            public String resolveStringValue(String strVal) {
                return getEnvironment().resolvePlaceholders(strVal);
            }
        });
    }

    // 先初始化所有 LoadTimeWeaver 类型的bean, 
    // 之前也说过, 这是AspectJ的内容, 先跳过
    String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
    for (String weaverAwareName : weaverAwareNames) {
        getBean(weaverAwareName);
    }

    // Stop using the temporary ClassLoader for type matching.
    beanFactory.setTempClassLoader(null);

    // 没有什么别的目的, 这时候Spring已经开始初始化所有Singleton Bean 了, 
    // 肯定不希望这时候还出现bean定义解析, 加载,注册
    beanFactory.freezeConfiguration();

    // 开始初始化
    beanFactory.preInstantiateSingletons();
}

ConversionService
ConversionService 最有用的场景就是,它用来将前端传过来的参数和后端的 controller 方法上的参数进行绑定的时候用。

像前端传过来的字符串、整数要转换为后端的 String、Integer 很容易,但是如果 controller 方法需要的是一个枚举值,或者是 Date 这些非基础类型(含基础类型包装类)值的时候,我们就可以考虑采用 ConversionService 来进行转换。

<bean id="conversionService"
  class="org.springframework.context.support.ConversionServiceFactoryBean">
  <property name="converters">
    <list>
      <bean class="com.javadoop.learning.utils.StringToEnumConverterFactory"/>
    </list>
  </property>
</bean>

ConversionService 接口很简单,所以要自定义一个 convert 的话也很简单。

下面再说一个实现这种转换很简单的方式,那就是实现 Converter 接口。

来看一个很简单的例子,这样比什么都管用。

public class StringToDateConverter implements Converter<String, Date> {

    @Override
    public Date convert(String source) {
        try {
            return DateUtils.parseDate(source, "yyyy-MM-dd", "yyyy-MM-dd HH:mm:ss", "yyyy-MM-dd HH:mm", "HH:mm:ss", "HH:mm");
        } catch (ParseException e) {
            return null;
        }
    }
}

只要注册这个 Bean 就可以了。这样,前端往后端传的时间描述字符串就很容易绑定成 Date 类型了,不需要其他任何操作。


从最后一行进入, 又到了 DefaultListableBeanFactory 类了, 这个类我们已经不陌生了

preInstantiateSingletons

// DefaultListableBeanFactory.java  728
@Override
public void preInstantiateSingletons() throws BeansException {
    if (this.logger.isDebugEnabled()) {
        this.logger.debug("Pre-instantiating singletons in " + this);
    }

    // this.beanDefinitionNames 保留了所有的beanNames
    List<String> beanNames = new ArrayList<String>(this.beanDefinitionNames);

    // 下面这个循环, 触发所有的非懒加载的singleton beans的初始化操作
    for (String beanName : beanNames) {

        // 合并父bean中的配置, 注意 <bean id="" class="" parent="" /> 中的parent, 用的不多
        RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);

        // 非抽象, 非懒加载的bean 如果配置了 abstract=true, 那就不需要初始化
        if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {

            // 处理FactoryBean
            if (isFactoryBean(beanName)) {

                // FactoryBean的话, 在beanName前面加上 '&' 符号, 再调用getBean()方法, getBean()方法先不急
                final FactoryBean<?> factory = (FactoryBean<?>) getBean(FACTORY_BEAN_PREFIX + beanName);

                // 判断当前FactoryBean是否是SmartFactoryBean的实现, 此处忽略
                boolean isEagerInit;
                if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
                    isEagerInit = AccessController.doPrivileged(new PrivilegedAction<Boolean>() {
                        @Override
                        public Boolean run() {
                            return ((SmartFactoryBean<?>) factory).isEagerInit();
                        }
                    }, getAccessControlContext());
                }
                else {
                    isEagerInit = (factory instanceof SmartFactoryBean &&
                            ((SmartFactoryBean<?>) factory).isEagerInit());
                }
                if (isEagerInit) {
                    getBean(beanName);
                }
            }
            else {
                // 对于普通的bean, 只要调用getBean(beanName)这个方法就可以进行初始化了
                getBean(beanName);
            }
        }
    }

    // 到这里, 所有的singleton beans都已经完成初始化
    // 如果我们定义的bean是实现了SmartInitializingSingleton接口的话, 在这里进行回调. 忽略
    for (String beanName : beanNames) {
        Object singletonInstance = getSingleton(beanName);
        if (singletonInstance instanceof SmartInitializingSingleton) {
            final SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
            if (System.getSecurityManager() != null) {
                AccessController.doPrivileged(new PrivilegedAction<Object>() {
                    @Override
                    public Object run() {
                        smartSingleton.afterSingletonsInstantiated();
                        return null;
                    }
                }, getAccessControlContext());
            }
            else {
                smartSingleton.afterSingletonsInstantiated();
            }
        }
    }
}

接下来我们就进入到了getBean(beanName)方法中了, 这个方法我们经常用来从beanFactory中获取一个bean, 而初始化的方法也在封装在了这个方法里.

getBean
在继续前进之前,先看看 FactoryBean 的预备知识


FactoryBean
FactoryBean 适用于 Bean 的创建过程比较复杂的场景,比如数据库连接池的创建。

public interface FactoryBean<T> {
    T getObject() throws Exception;
    Class<T> getObjectType();
    boolean isSingleton();
}
public class Person { 
    private Car car ;
    private void setCar(Car car){ this.car = car;  }  
}

我们假设现在需要创建一个 Person 的 Bean,首先我们需要一个 Car 的实例,我们这里假设 Car 的实例创建很麻烦,那么我们可以把创建 Car 的复杂过程包装起来:

public class MyCarFactoryBean implements FactoryBean<Car>{
    private String make; 
    private int year ;

    public void setMake(String m){ this.make =m ; }

    public void setYear(int y){ this.year = y; }

    public Car getObject(){ 
      // 这里我们假设 Car 的实例化过程非常复杂,反正就不是几行代码可以写完的那种
      CarBuilder cb = CarBuilder.car();

      if(year!=0) cb.setYear(this.year);
      if(StringUtils.hasText(this.make)) cb.setMake( this.make ); 
      return cb.factory(); 
    }

    public Class<Car> getObjectType() { return Car.class ; } 

    public boolean isSingleton() { return false; }
}

我们看看装配的时候是怎么配置的:

<bean class = "com.javadoop.MyCarFactoryBean" id = "car">
  <property name = "make" value ="Honda"/>
  <property name = "year" value ="1984"/>
</bean>
<bean class = "com.javadoop.Person" id = "josh">
  <property name = "car" ref = "car"/>
</bean>

看到不一样了吗?id 为 “car” 的 bean 其实指定的是一个 FactoryBean,不过配置的时候,我们直接让配置 Person 的 Bean 直接依赖于这个 FactoryBean 就可以了。中间的过程 Spring 已经封装好了。

说到这里,我们再来点干货。我们知道,现在还用 xml 配置 Bean 依赖的越来越少了,更多时候,我们可能会采用 java config 的方式来配置,这里有什么不一样呢?

@Configuration 
public class CarConfiguration { 

    @Bean 
    public MyCarFactoryBean carFactoryBean(){ 
      MyCarFactoryBean cfb = new MyCarFactoryBean();
      cfb.setMake("Honda");
      cfb.setYear(1984);
      return cfb;
    }

    @Bean
    public Person aPerson(){ 
    Person person = new Person();
      // 注意这里的不同
    person.setCar(carFactoryBean().getObject());
    return person; 
    } 
}

这个时候,其实我们的思路也很简单,把 MyCarFactoryBean 看成是一个简单的 Bean 就可以了,不必理会什么 FactoryBean,它是不是 FactoryBean 和我们没关系。


// AbstractBeanFactory.java 195
@Override
public Object getBean(String name) throws BeansException {
    return doGetBean(name, null, null, false);
}


// 我们剖析初始化bean的过程, 但是getBean方法我们经常是用来从容器中获取bean用的, 注意切换思路
// 已经初始化的bean就从容器中直接获取, 否则就先初始化再返回
protected <T> T doGetBean(
        final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)
        throws BeansException {

    // 获取一个"正统"的beanName, 处理两种情况:
    // 一种是前面说的FactoryBean(名称前加 "&")
    // 另一种就是别名, 因为这个方法是getBean, 获取bean用的, 传入一个别名也是可以的
    final String beanName = transformedBeanName(name);

    // 注意这个, 这是返回值
    Object bean;

    // 检查一下是不是已经创建过了
    Object sharedInstance = getSingleton(beanName);

    // 这里说下args, 虽然看上去不重要. 前面我们一路进来都是getBean(beanName),
    // 所以这里args是null, 但是如果args不为null的时候, 说明想要调用方不是希望获取bean, 而是创建bean
    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的话, 直接返回这个 sharedInstance
        // 如果是FactoryBean, 返回他创建的那个实例对象
        bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
    }

    else {
        // 如果创建了此beanName的prototype类型的bean, 直接抛错
        // 往往是因此陷入了循环引用
        if (isPrototypeCurrentlyInCreation(beanName)) {
            throw new BeanCurrentlyInCreationException(beanName);
        }

        // 检查一下这个BeanDefinition是否存在容器中
        BeanFactory parentBeanFactory = getParentBeanFactory();
        if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
            // 如果当前容器中没有这个BeanDefinition, 看看父容器中有没有
            String nameToLookup = originalBeanName(name);
            if (args != null) {
                // 返回父容器的查询结果
                return (T) parentBeanFactory.getBean(nameToLookup, args);
            }
            else {
                // No args -> delegate to standard getBean method.
                return parentBeanFactory.getBean(nameToLookup, requiredType);
            }
        }

        // typeCheckOnly为false, 将当前beanName放入一个alreadyCreated的Set集合中
        if (!typeCheckOnly) {
            markBeanAsCreated(beanName);
        }

        // 到这里总结一下, 要准备创建bean了
        // 对于Singleton的bean来说, 容器中还没有创建这个bean
        // 对于prototype的bean来说, 本来就是要新创建一个bean
        try {
            final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
            checkMergedBeanDefinition(mbd, beanName, args);

            // 先初始化所有依赖的bean
            // 注意, 这里依赖的bean指的是 depends-on中定义的依赖
            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 + "'");
                    }
                    // 注册一下依赖关系
                    registerDependentBean(dep, beanName);
                    // 先初始化被依赖的bean
                    getBean(dep);
                }
            }

            // 如果是Singleton scope , 创建Singleton实例
            if (mbd.isSingleton()) {
                sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {
                    @Override
                    public Object getObject() throws BeansException {
                        try {
                            // 执行创建bean, 详情后面说
                            return createBean(beanName, mbd, args);
                        }
                        catch (BeansException ex) {
                            destroySingleton(beanName);
                            throw ex;
                        }
                    }
                });
                bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
            }

            // 如果是prototype scope的, 创建prototype实例
            else if (mbd.isPrototype()) {
                // It's a prototype -> create a new instance.
                Object prototypeInstance = null;
                try {
                    beforePrototypeCreation(beanName);
                    // 执行创建bean
                    prototypeInstance = createBean(beanName, mbd, args);
                }
                finally {
                    afterPrototypeCreation(beanName);
                }
                bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
            }

            // 如果不是Singleton或prototype的话, 需要委托给相应实现类进行处理  
            else {
                String scopeName = mbd.getScope();
                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, new ObjectFactory<Object>() {
                        @Override
                        public Object getObject() throws BeansException {
                            beforePrototypeCreation(beanName);
                            try {
                                // 执行创建bean
                                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;
        }
    }

    // 最后检查一下要返回的类型对不对, 不对的话抛异常, 对的话就返回了
    if (requiredType != null && bean != null && !requiredType.isInstance(bean)) {
        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;
}

接下来是分析 createBean 方法:

protected abstract Object createBean(String beanName, RootBeanDefinition mbd, Object[] args)
        throws BeanCreationException;

第三个参数 args 代表的创建实例需要的参数, 就是给构造器的参数或者是给FactoryBean的参数. 不过在我们的初始化阶段, args为null

这会我们到了一个新的类了, AbstractAutowireCapableBeanFactory . 看类名, AutowireCapable, 类名是不是也说明了些问题? 自动装配的能力

主要是为了以下场景,采用 @Autowired 注解注入属性值:

public class MessageServiceImpl implements MessageService {
    @Autowired
    private UserService userService;

    public String getMessage() {
        return userService.getMessage();
    }
}
<bean id="messageService" class="com.javadoop.example.MessageServiceImpl" />

以上这种属于混用了 xml 和 注解 两种方式的配置方式,Spring 会处理这种情况。

// AbstractAutowireCapableBeanFactory 447
@Override
protected Object createBean(String beanName, RootBeanDefinition mbd, Object[] args) throws BeanCreationException {
    if (logger.isDebugEnabled()) {
        logger.debug("Creating instance of bean '" + beanName + "'");
    }
    RootBeanDefinition mbdToUse = mbd;

    // 确保BeanDefinition中的class被加载
    Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
    if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
        mbdToUse = new RootBeanDefinition(mbd);
        mbdToUse.setBeanClass(resolvedClass);
    }

    // 准备方法覆写,这里又涉及到一个概念:MethodOverrides,它来自于 bean 定义中的 <lookup-method /> 
    // 和 <replaced-method />,如果读者感兴趣,回到 bean 解析的地方看看对这两个标签的解析。
    try {
        mbdToUse.prepareMethodOverrides();
    }
    catch (BeanDefinitionValidationException ex) {
        throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
                beanName, "Validation of method overrides failed", ex);
    }

    try {
        // 让 InstantiationAwareBeanPostProcessor  在这一步有机会返回代理
        Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
        if (bean != null) {
            return bean;
        }
    }
    catch (Throwable ex) {
        throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
                "BeanPostProcessor before instantiation of bean failed", ex);
    }

    // 重头戏 创建bean
    Object beanInstance = doCreateBean(beanName, mbdToUse, args);
    if (logger.isDebugEnabled()) {
        logger.debug("Finished creating instance of bean '" + beanName + "'");
    }
    return beanInstance;
}

创建 Bean

我们继续往里看 doCreateBean 这个方法:


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

    // Instantiate the bean.
    BeanWrapper instanceWrapper = null;
    if (mbd.isSingleton()) {
        instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
    }
    if (instanceWrapper == null) {
        // 说明不是FactoryBean, 这里实例化bean, 非常关键. 细节之后再说
        instanceWrapper = createBeanInstance(beanName, mbd, args);
    }
    // 这里就是bean里面,我们定义的类的实例.
    final Object bean = (instanceWrapper != null ? instanceWrapper.getWrappedInstance() : null);
    // 类型
    Class<?> beanType = (instanceWrapper != null ? instanceWrapper.getWrappedClass() : null);
    mbd.resolvedTargetType = beanType;

    // 直接跳过 涉及接口 MergedBeanDefinitionPostProcessor
    synchronized (mbd.postProcessingLock) {
        if (!mbd.postProcessed) {
            try {
                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.
    // 下面这块代码是为了解决循环依赖的问题
    boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
            isSingletonCurrentlyInCreation(beanName));
    if (earlySingletonExposure) {
        if (logger.isDebugEnabled()) {
            logger.debug("Eagerly caching bean '" + beanName +
                    "' to allow for resolving potential circular references");
        }
        addSingletonFactory(beanName, new ObjectFactory<Object>() {
            @Override
            public Object getObject() throws BeansException {
                return getEarlyBeanReference(beanName, mbd, bean);
            }
        });
    }

    // Initialize the bean instance.
    Object exposedObject = bean;
    try {
        // 这一步也是非常关键的, 这一步负责属性装配, 因为前面只是实例化了, 并没有设值. 在这里设置属性值
        populateBean(beanName, mbd, instanceWrapper);
        if (exposedObject != null) {
            // 还记得 init-method 吗?还有 InitializingBean 接口?还有 BeanPostProcessor 接口?
            // 这里就是处理 bean 初始化完成后的各种回调
            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);
        }
    }

    if (earlySingletonExposure) {
        Object earlySingletonReference = getSingleton(beanName, false);
        if (earlySingletonReference != null) {
            if (exposedObject == bean) {
                exposedObject = earlySingletonReference;
            }
            else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
                String[] dependentBeans = getDependentBeans(beanName);
                Set<String> actualDependentBeans = new LinkedHashSet<String>(dependentBeans.length);
                for (String dependentBean : dependentBeans) {
                    if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
                        actualDependentBeans.add(dependentBean);
                    }
                }
                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.
    try {
        registerDisposableBeanIfNecessary(beanName, bean, mbd);
    }
    catch (BeanDefinitionValidationException ex) {
        throw new BeanCreationException(
                mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
    }

    return exposedObject;
}

到这里,我们已经分析完了 doCreateBean()方法, 总的来说, 我们已经说完了整个初始化流程

接下来说说doCreateBean方法的三个细节.
一个是创建Bean的createBeanInstance方法, 一个是依赖注入的populateBean方法, 还有一个是回调initializeBean方法

创建bean实例
我们先看createBeanInstance方法, 挑重点的说,这个方法就是实例化我们指定的类.

protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, Object[] args) {
    // 确保已经加载了此类
    Class<?> beanClass = resolveBeanClass(mbd, beanName);

    // 校验一下这个类的访问权限
    if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) {
        throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                "Bean class isn't public, and non-public access not allowed: " + beanClass.getName());
    }

    if (mbd.getFactoryMethodName() != null)  {
        // 采用工厂方法实例化, 注意, 不是FactoryBean
        return instantiateUsingFactoryMethod(beanName, mbd, args);
    }

    // 如果不是第一次创建, 比如prototype创建第二次
    // 这种情况下, 我们可以从第一次创建知道, 采用无参构造方法,还是构造函数依赖注入 来完成实例化
    boolean resolved = false;
    boolean autowireNecessary = false;
    if (args == null) {
        synchronized (mbd.constructorArgumentLock) {
            if (mbd.resolvedConstructorOrFactoryMethod != null) {
                resolved = true;
                autowireNecessary = mbd.constructorArgumentsResolved;
            }
        }
    }
    // 如果已经创建过, 就不用再去做构造函数判断了
    if (resolved) {
        if (autowireNecessary) {
            // 构造函数 依赖注入
            return autowireConstructor(beanName, mbd, null, null);
        }
        else {
            // 无惨构造方法
            return instantiateBean(beanName, mbd);
        }
    }

    // 判断是否采用有参构造函数
    Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
    if (ctors != null ||
            mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR ||
            mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args))  {
        // 构造函数依赖注入
        return autowireConstructor(beanName, mbd, ctors, args);
    }

    // 调用无参构造函数
    return instantiateBean(beanName, mbd);
}

挑个简单的无参构造函数构造实例来看看:

protected BeanWrapper instantiateBean(final String beanName, final RootBeanDefinition mbd) {
    try {
        Object beanInstance;
        final BeanFactory parent = this;
        if (System.getSecurityManager() != null) {
            beanInstance = AccessController.doPrivileged(new PrivilegedAction<Object>() {
                @Override
                public Object run() {
                    return getInstantiationStrategy().instantiate(mbd, beanName, parent);
                }
            }, getAccessControlContext());
        }
        else {
            // 实例化
            beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, parent);
        }
        // 包装一下 , 返回
        BeanWrapper bw = new BeanWrapperImpl(beanInstance);
        initBeanWrapper(bw);
        return bw;
    }
    catch (Throwable ex) {
        throw new BeanCreationException(
                mbd.getResourceDescription(), beanName, "Instantiation of bean failed", ex);
    }
}

我们可以看到, 关键地方在于 :

beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, parent);

这里会进行实际的实例化过程,我们进去看看:

// SimpleInstantiationStrategy 59
@Override
public Object instantiate(RootBeanDefinition bd, String beanName, BeanFactory owner) {
    // 如果不存在方法覆写, 就使用反射进行实例化. 否侧使用CGLIB
    if (bd.getMethodOverrides().isEmpty()) {
        Constructor<?> constructorToUse;
        synchronized (bd.constructorArgumentLock) {
            constructorToUse = (Constructor<?>) bd.resolvedConstructorOrFactoryMethod;
            if (constructorToUse == null) {
                final Class<?> clazz = bd.getBeanClass();
                if (clazz.isInterface()) {
                    throw new BeanInstantiationException(clazz, "Specified class is an interface");
                }
                try {
                    if (System.getSecurityManager() != null) {
                        constructorToUse = AccessController.doPrivileged(new PrivilegedExceptionAction<Constructor<?>>() {
                            @Override
                            public Constructor<?> run() throws Exception {
                                return clazz.getDeclaredConstructor((Class[]) null);
                            }
                        });
                    }
                    else {
                        constructorToUse =    clazz.getDeclaredConstructor((Class[]) null);
                    }
                    bd.resolvedConstructorOrFactoryMethod = constructorToUse;
                }
                catch (Throwable ex) {
                    throw new BeanInstantiationException(clazz, "No default constructor found", ex);
                }
            }
        }
        // 利用构造方法进行实例化
        return BeanUtils.instantiateClass(constructorToUse);
    }
    else {
        // 存在方法覆写, 利用CGLIB来完成实例化, 需要依赖CGLIB生成子类
        // tips: 因为如果不使用 CGLIB 的话,存在 override 的情况 JDK 并没有提供相应的实例化支持
        return instantiateWithMethodInjection(bd, beanName, owner);
    }
}

到这里,我们就算实例化完成了。我们开始说怎么进行属性注入。

bean属性注入

看完了 createBeanInstance(…) 方法,我们来看看 populateBean(…) 方法,该方法负责进行属性设值,处理依赖。


protected void populateBean(String beanName, RootBeanDefinition mbd, BeanWrapper bw) {
    // bean实例的所有属性都在这里了
    PropertyValues pvs = mbd.getPropertyValues();

    if (bw == null) {
        if (!pvs.isEmpty()) {
            throw new BeanCreationException(
                    mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");
        }
        else {
            // Skip property population phase for null instance.
            return;
        }
    }

    // 到这一步的时候, bean实例化完成 (通过工厂方法或构造函数) , 但是还没开始属性设值
    // InstantiationAwareBeanPostProcessor 的实现类可以在这里对bean进行状态修改
    // 我也没找到有实际的使用,所以我们暂且忽略这块吧
    boolean continueWithPropertyPopulation = true;

    if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
        for (BeanPostProcessor bp : getBeanPostProcessors()) {
            if (bp instanceof InstantiationAwareBeanPostProcessor) {
                InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
                // 如果返回false, 代表不需要 进行后续的属性修改也不需要再经过其他的BeanPostProcessor处理
                if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
                    continueWithPropertyPopulation = false;
                    break;
                }
            }
        }
    }

    if (!continueWithPropertyPopulation) {
        return;
    }

    if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME ||
            mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
        MutablePropertyValues newPvs = new MutablePropertyValues(pvs);

        // 通过名字找到所有的属性值, 如果是bean依赖, 先初始化依赖的bean, 记录依赖关系
        if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME) {
            autowireByName(beanName, mbd, bw, newPvs);
        }

        // 通过类型装配, 复杂一些
        if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
            autowireByType(beanName, mbd, bw, newPvs);
        }

        pvs = newPvs;
    }

    boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
    boolean needsDepCheck = (mbd.getDependencyCheck() != RootBeanDefinition.DEPENDENCY_CHECK_NONE);

    if (hasInstAwareBpps || needsDepCheck) {
        PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
        if (hasInstAwareBpps) {
            for (BeanPostProcessor bp : getBeanPostProcessors()) {
                if (bp instanceof InstantiationAwareBeanPostProcessor) {
                    InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;

                    // 这里有个非常有用的BeanPostProcessor进到这里 : AutowiredAnnotationBeanPostProcessor
                    // 对采用@Autowire, @Value注解的进行设值
                    pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
                    if (pvs == null) {
                        return;
                    }
                }
            }
        }
        if (needsDepCheck) {
            checkDependencies(beanName, mbd, filteredPds, pvs);
        }
    }

    // 设置 bean 实例的属性值
    applyPropertyValues(beanName, mbd, bw, pvs);
}

initializeBean

属性注入完成之后, 这一步其实就是处理回调了.这块代码比较简单


protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) {
    if (System.getSecurityManager() != null) {
        AccessController.doPrivileged(new PrivilegedAction<Object>() {
            @Override
            public Object run() {
                invokeAwareMethods(beanName, bean);
                return null;
            }
        }, getAccessControlContext());
    }
    else {
        // 如果Bean实现了BeanNameAware, BeanClassLoaderAware, 或 BeanFactoryAware接口, 回调
        invokeAwareMethods(beanName, bean);
    }

    Object wrappedBean = bean;
    if (mbd == null || !mbd.isSynthetic()) {
        // BeanPostProcessor的postProcessorBeforeInitialization回调
        wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
    }

    try {
        // 处理bean中定义的 init-method
        // 或者如果bean实现了InitializingBean , 调用 afterPropertiesSet()方法
        invokeInitMethods(beanName, wrappedBean, mbd);
    }
    catch (Throwable ex) {
        throw new BeanCreationException(
                (mbd != null ? mbd.getResourceDescription() : null),
                beanName, "Invocation of init method failed", ex);
    }

    if (mbd == null || !mbd.isSynthetic()) {
        // BeanPostProcessor的postProcessorAfterInitialization回调
        wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
    }
    return wrappedBean;
}

   转载规则


《Spring IOC 容器源码分析笔记 (一)》 echi1995 采用 知识共享署名 4.0 国际许可协议 进行许可。
 上一篇
J.U.C (一) J.U.C (一)
整体认识J.U.C, 之前也写过AQS相关的博客, 那时候听了一节课就匆匆忙忙的记笔记写博客, 对J.U.C也没有一个系统的学习. 最近翻到一篇博客写的挺全的,想拿来学习一下. 深入浅出Java Concurrcy 整体认识首先要对J.U.
下一篇 
HashMap的最大容量是多少. HashMap的最大容量是多少.
HashMap的最大容量是多少.首先, HashMap底层是数组+链表, 所以HashMap的容量约等于 数组长度 * 链表长度.因为链表长度不固定,甚至可能链表会是树结构, 所以我们主要讨论数组长度. 那么, 数组的最大长度是多长呢? 仔
  目录