Spring 源码阅读-IOC容器的启动过程

本文档基于Spring 5.1.4.RELEASE版本进行编写。

提前说一下,主要是为了给自己留一个印象,整篇下来更像是对源码的跟踪记录,想看整体概括描述的话可以看Spring 的骨骼架构。
其中bean的创建过程、动态代理和循环依赖的解决办法都没写,是因为文章的长度太长,写到另一个文章里面了,Spring 源码阅读-bean的创建、循环依赖的处理以及代理

在本文中,会使用加载配置文件的形式来完成容器的创建,展示的是ClassPathXmlApplicationContext的工作流程。
可以使用下面这段代码作为入口,来了解整个框架的启动过程。

ClassPathXmlApplicationContext类结构图

在示例项目中使用的ClassPathXmlApplicationContext并不会被注册为bean,所以InitializingBean的逻辑是不会工作的。

// 测试程序入口

ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext(new String[] {"spring-config.xml"}, true, null);
HelloService helloService = (HelloService) ac.getBean("helloService");
helloService.sayHello();

1. Spring 框架的启动过程

1.1. 容器的创建

1.1.1. 构造函数

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

    // ---------------------------------------------- 设置父级 ------------------------------------------------

    // 在父级AbstractApplicationContext里面会创建一个ResourcePatternResolver类型的实例对象。
    super(parent);

    // ---------------------------------------- 解析传入的配置文件的地址 ------------------------------------------

    // 解析传入的配置文件的地址,将结果存储在 AbstractRefreshableConfigApplicationContext 类的 configLocations 全局属性中
    setConfigLocations(configLocations);

    // ------------------------------------------- 容器的刷新 ------------------------------------------------

    // 这个的逻辑比较长,为了文档目录看的好看,这里会在 容器的创建 同级添加一个标题 容器的刷新 来说明
    if (refresh) {
        refresh();
    }
}

1.1.2. 对父级构造函数的调用

ClassPathXmlApplicationContext的构造函数里有对父级的调用,整个调用过程是这样的
ClassPathXmlApplicationContext -> AbstractXmlApplicationContext -> AbstractRefreshableConfigApplicationContext
-> AbstractRefreshableApplicationContext -> AbstractApplicationContext
其中只有AbstractApplicationContext类内被调用的构造函数有点特殊。

public AbstractApplicationContext(@Nullable ApplicationContext parent) {
    this();
    setParent(parent);
}

public AbstractApplicationContext() {
    // 创建一个ResourcePatternResolver类型的实例对象
    // 这个东西是用来 把配置文件从地址字符串读取成Resource的,Resource是计算机文件的抽象存在。
    this.resourcePatternResolver = getResourcePatternResolver();
}

// AbstractApplicationContext
protected ResourcePatternResolver getResourcePatternResolver() {
    return new PathMatchingResourcePatternResolver(this);
}
PropertyResolver结构图

1.1.3. 解析传入的配置文件的地址

这个步骤就是为了解析配置文件的地址,如果给定的地址中有占位符,则通过相应的环境属性值替换占位符。

// AbstractRefreshableConfigApplicationContext
public void setConfigLocations(@Nullable String... locations) {
    if (locations != null) {
        Assert.noNullElements(locations, "Config locations must not be null");
        this.configLocations = new String[locations.length];
        for (int i = 0; i < locations.length; i++) {
            this.configLocations[i] = resolvePath(locations[i]).trim();
        }
    }
    else {
        this.configLocations = null;
    }
}

// AbstractRefreshableConfigApplicationContext
protected String resolvePath(String path) {
    // 通过换环境属性值替换占位符,这里不继续跟了,先看可以自己看看
    return getEnvironment().resolveRequiredPlaceholders(path);
}

// AbstractApplicationContext
public ConfigurableEnvironment getEnvironment() {
    // 这个环境可以在程序入口手动设置,不过需要使用 ConfigurableApplicationContext 作为父类引用指向 ClassPathXmlApplicationContext 对象实例
    if (this.environment == null) {
        // 这里面创建的是 StandardEnvironment 对象实例
        this.environment = createEnvironment();
    }
    return this.environment;
}

上面代码中可以看出来配置文件的地址允许使用占位符,这里展示一下简单使用示例

new ClassPathXmlApplicationContext("spring-${type}.xml");
// 这个东西有使用前提,你必须想办法将在容器启动前把这个type放到环境变量

1.2 容器的刷新

容器刷新的主要目的是完成 bean 的创建和响应组件的创建,使得Spring Core的核心逻辑能够执行。

// AbstractApplicationContext
public void refresh() throws BeansException, IllegalStateException {
    synchronized (this.startupShutdownMonitor) {
        // -------------------------------------------- 完成一些验证、准备操作 ---------------------------------------------
        // Prepare this context for refreshing.
        prepareRefresh();

        // ------------------------------------------ 刷新当前IOC容器持有的内部容器 ----------------------------------------

        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) {
            // --------------------------------------------- 处理IOC容器刷新异常时的行为 ----------------------------------------

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

            // 销毁已经创建的单例
            destroyBeans();

            // 重置 active 标识为 false,它用来标识当前上下文是否活跃的
            cancelRefresh(ex);

            // Propagate exception to caller.
            throw ex;
        }

        finally {
            // ---------------------------------------- 清除在上述过程中产生的内省缓存数据 -----------------------------------

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

1.2.1. prepareRefresh(完成一些验证、准备操作)

结论先行,这个方法总体做了4件事情
1.设置一些标志属性
2.调用initPropertySources()方法
3.对环境中必须的属性进行验证
4.为早期的ApplicationEvents分配集合

// AbstractApplicationContext
protected void prepareRefresh() {
    // -------------------------------- 设置一些标志属性 --------------------------------
    this.startupDate = System.currentTimeMillis();
    this.closed.set(false); // 标识当前上下文没有处于关闭状态
    this.active.set(true); // 标识当前上下文处于活跃状态

    if (logger.isDebugEnabled()) {
        if (logger.isTraceEnabled()) {
            logger.trace("Refreshing " + this);
        }
        else {
            logger.debug("Refreshing " + getDisplayName());
        }
    }

    // -------------------------------- 调用initPropertySources()方法 -------------------------

    // Initialize any placeholder property sources in the context environment (初始化在上下文环境中的所有占位符属性源)
    // 这个是交由子类实现的,默认情况下什么都不做,可以自己搞一个容器的实现类试试重写这个方法。
    initPropertySources();

    // -------------------------------- 对环境中必须的属性进行验证 -------------------------

    // Validate that all properties marked as required are resolvable (验证所有被标记为required的属性是存在的,如果有找不到的会抛出异常)
    // getEnvironment() 在上面有说过,默认使用的是 StandardEnvironment 对象实例
    // 可以在 initPropertySources() 的实现里面通过调用 getEnvironment().setRequiredProperties("xxx"); 添加required的属性
    getEnvironment().validateRequiredProperties();

    // ----------------------------- 为早期的ApplicationEvents分配集合 ---------------------

    // Allow for the collection of early ApplicationEvents,
    // to be published once the multicaster is available...
    // 为早期的ApplicationEvents分配一个集合,在之后事件多播器创建完成后会将集合内堆积的事件进行发布。
    // 就如同送信,你的信交给邮局,总得有邮递员去送出去,没有邮递员的时候,信会在邮局堆积,这里就是earlyApplicationEvents就类似临时邮局,多播器就相当于邮递员。(例子有点不恰当)
    this.earlyApplicationEvents = new LinkedHashSet<>(); 
}

// AbstractPropertyResolver
public void validateRequiredProperties() {
    MissingRequiredPropertiesException ex = new MissingRequiredPropertiesException();
    for (String key : this.requiredProperties) {
        if (this.getProperty(key) == null) {
            ex.addMissingRequiredProperty(key);
        }
    }
    if (!ex.getMissingRequiredProperties().isEmpty()) { // 如果异常集合不为空,就抛出异常
        throw ex;
    }
}

1.2.2. obtainFreshBeanFactory(刷新当前IOC容器持有的内部容器)

当前IOC容器ApplicationContext容器内部IOC容器指的是BeanFactory容器,它也是IOC容器。
也就是说IOC容器有两类,分别是ApplicationContext容器BeanFactory容器

这个方法的主要逻辑是
创建一个新的内部IOC容器(DefaultListableBeanFactory类型的),然后使用这个容器去解析配置文件,将解析到的BeanDefinition存到IOC容器中等待下一步的操作(也就是用到是进行实例化)。

BeanDefinition并不是我们使用的那些Bean的实例对象,它是我们交由IOC容器管理的bean的相关信息,每个bean都对应一个BeanDefinition对象。

// AbstractApplicationContext
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
    // 创建新的 BeanFactory 容器,并且对配置文件进行解析,完成对 BeanDefinition 的注册
    refreshBeanFactory();
    return getBeanFactory(); // 返回这个刚创建的 IOC容器
}

// AbstractRefreshableApplicationContext
protected final void refreshBeanFactory() throws BeansException {
    // ---------------------------------------- 销毁已经存在的BeanFactory容器(内部IOC容器) ----------------------------------

    // 每次刷新都会导致创建新的内部IOC容器,如果之前有,代表之前调用过上下文的刷新方法。
    if (hasBeanFactory()) { // 如果已经有BeanFactory了 -> 销毁。
        destroyBeans();  // 销毁存在的IOC容器内的Bean
        closeBeanFactory(); // 清除存在的IOC容器(设置为null,等待垃圾回收处理)
    }
    try {
        // ---------------------------------------- 构建新的的BeanFactory容器(内部IOC容器) ----------------------------------

        DefaultListableBeanFactory beanFactory = createBeanFactory(); // 创建一个新的BeanFactory容器
        beanFactory.setSerializationId(getId());
        customizeBeanFactory(beanFactory); // 这个可以注意下,可以自定义内部IOC容器是否允许BeanDefinition覆盖 和 是否允许循环引用

        // -------------------------------------- 从配置文件中解析BeanDefinition -------------------------------

        loadBeanDefinitions(beanFactory);
        synchronized (this.beanFactoryMonitor) {
            this.beanFactory = beanFactory;
        }
    }
    catch (IOException ex) {
        throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
    }
}

1.2.2.1. createBeanFactory

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

protected BeanFactory getInternalParentBeanFactory() {
    // getParent() 获取的就是父级的IOC容器,Spring MVC框架启动时应该会用到,这里用不到
    return (getParent() instanceof ConfigurableApplicationContext ?
            ((ConfigurableApplicationContext) getParent()).getBeanFactory() : getParent());
}

这里主要就是想看DefaultListableBeanFactory的类结构关系,方便理解后续逻辑。

DefaultListableBeanFactory 类结构关系

1.2.2.2. customizeBeanFactory

// AbstractRefreshableApplicationContext
protected void customizeBeanFactory(DefaultListableBeanFactory beanFactory) {
    // 设置 IOC容器是否允许BeanDefinition覆盖 和 是否允许循环引用
    if (this.allowBeanDefinitionOverriding != null) {
        beanFactory.setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
    }
    if (this.allowCircularReferences != null) {
        beanFactory.setAllowCircularReferences(this.allowCircularReferences);
    }
}
// 使用方式,要在上下文刷新之前设置。

ClassPathXmlApplicationContext ac = ...
ac.setAllowBeanDefinitionOverriding(false);
ac.setAllowCircularReferences(false);
ac.refresh();

1.2.2.3. loadBeanDefinitions

这个方法内有两个主要逻辑
1.组装一个XmlBeanDefinitionReader对象
2.使用组装的对象去解析配置文件中的内容,将解析到的BeanDefinition放入IOC容器内。

提醒:这个方法的调用链有点长,而且调用链中方法名重复性也很高

// AbstractXmlApplicationContext
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
    // ---------------------------------------- 组装XmlBeanDefinitionReader对象 ---------------------------------------------
    // XmlBeanDefinitionReader对象的作用是解析配置文件(Xml),从中解析出来 BeanDefinition 放入IOC容器中

    // Create a new XmlBeanDefinitionReader for the given BeanFactory. (为给定的 IOC容器 创建一个 XmlBeanDefinitionReader 实例对象)
    // 这里需要注意下 XmlBeanDefinitionReader 的构造函数
    // 它会把传入的IOC容器保存在自己的对象实例内,方便后续解析BeanDefinition时直接添加到IOC容器内。
    XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);

    // 这里的 this 是 ClassPathXmlApplicationContext对象实例,毕竟一开始创建的就是它,别记错。
    beanDefinitionReader.setEnvironment(this.getEnvironment());
    beanDefinitionReader.setResourceLoader(this);
    // EntityResolver 对象在讲配置文件读成 Document 时有时用到
    // 具体可见 XmlBeanDefinitionReader#doLoadBeanDefinitions 里面的逻辑,下面分析的步骤中有。
    beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));

    // 允许子类提供读取器的自定义初始化,然后继续实际加载bean定义。
    initBeanDefinitionReader(beanDefinitionReader);

    // ------------------------------------- 使用XmlBeanDefinitionReader对象解析配置文件 ----------------------------------------

    loadBeanDefinitions(beanDefinitionReader);
}

这个方法内的有些方法调用都挺值的注意的,下面细看具体方法。

// AbstractBeanDefinitionReader 
// 这个类是 XmlBeanDefinitionReader 的父类,XmlBeanDefinitionReader 的构造函数里调用了 super
protected AbstractBeanDefinitionReader(BeanDefinitionRegistry registry) {
    Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
    this.registry = registry; // 在 AbstractBeanDefinitionReader 中持有传入的这个IOC容器

    // 按照 DefaultListableBeanFactory 的类结构图,这里必定会走到 else 代码块里。
    if (this.registry instanceof ResourceLoader) {
        this.resourceLoader = (ResourceLoader) this.registry;
    }
    else {
        // 之前也说过 这个东西是用来 把配置文件从名称字符串读取成Resource的。
        // 实际上,在现有逻辑内,这里创建的这个实例没什么用,在上层方法内会覆盖这个环境赋值
        this.resourceLoader = new PathMatchingResourcePatternResolver();
    }

    // 按照 DefaultListableBeanFactory 的类结构图,这里必定会走到 else 代码块里。
    if (this.registry instanceof EnvironmentCapable) {
        this.environment = ((EnvironmentCapable) this.registry).getEnvironment();
    }
    else {
        // 这里又创建了一个环境,之前在 AbstractApplicationContext 中也有
        // 这个实例也会被上层方法覆盖,没什么用。
        this.environment = new StandardEnvironment();
    }
}

// AbstractXmlApplicationContext
protected void initBeanDefinitionReader(XmlBeanDefinitionReader reader) {
    // 如果 validating 为true,代表会进行xml验证,如果关闭验证,此方法将打开名称空间感知,以便在这种情况下仍然正确处理模式名称空间。
    reader.setValidating(this.validating);
}

// AbstractXmlApplicationContext
protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException {
    Resource[] configResources = getConfigResources();
    if (configResources != null) {
        reader.loadBeanDefinitions(configResources);
    }
    // 按照示例代码的逻辑,在这个方法才能获取到值。
    // configLocations 存放的是 Spring 框架 配置文件的存放地址
    String[] configLocations = getConfigLocations();
    if (configLocations != null) {
        // 通过 reader 来解析 xml 配置文件,下面继续分析这个方法
        reader.loadBeanDefinitions(configLocations);
    }
}

// ClassPathXmlApplicationContext
protected Resource[] getConfigResources() {
    // 按照示例代码的逻辑,这里没有值
    return this.configResources;
}

// AbstractRefreshableConfigApplicationContext
protected String[] getConfigLocations() {
    // 在之前 ClassPathXmlApplicationContext 的构造函数中通过调用 setConfigLocations 方法已经设置过值了。
    // getDefaultConfigLocations() 默认情况下也是返回 null
    return (this.configLocations != null ? this.configLocations : getDefaultConfigLocations());
}

上面的代码已经由AbstractRefreshableApplicationContext#loadBeanDefinitions(DefaultListableBeanFactory)走到了
AbstractXmlApplicationContext#AbstractXmlApplicationContext(XmlBeanDefinitionReader)里,但逻辑还没有完成。

现在要进入到AbstractBeanDefinitionReader#loadBeanDefinitions(String[])里看看是如何解析Xml文件的。

// AbstractBeanDefinitionReader
public int loadBeanDefinitions(String... locations) throws BeanDefinitionStoreException {
    Assert.notNull(locations, "Location array must not be null");
    int count = 0;
    for (String location : locations) { // 迭代处理传入的多个配置文件的地址,示例代码实际只穿了1个
        count += loadBeanDefinitions(location);
    }
    return count;
}

// AbstractBeanDefinitionReader
public int loadBeanDefinitions(String location) throws BeanDefinitionStoreException {
    return loadBeanDefinitions(location, null);
}

// AbstractBeanDefinitionReader
public int loadBeanDefinitions(String location, @Nullable Set actualResources) throws BeanDefinitionStoreException {
    // 这里尝试获取的 ResourceLoader 就是 AbstractXmlApplicationContextloadBeanDefinitions(DefaultListableBeanFactory) 里设置的值
    // 实际上就是程序入口创建的 ClassPathXmlApplicationContext 对象实例。
    ResourceLoader resourceLoader = getResourceLoader();
    if (resourceLoader == null) {
        throw new BeanDefinitionStoreException(
                "Cannot load bean definitions from location [" + location + "]: no ResourceLoader available");
    }

    // 根据 ClassPathXmlApplicationContext 的类文件结构图,可以确定这里会进入 if 代码块
    if (resourceLoader instanceof ResourcePatternResolver) {
        // Resource pattern matching available.
        try {
            // 将 配置文件地址 解析成 Resource 对象
            Resource[] resources = ((ResourcePatternResolver) resourceLoader).getResources(location);
            int count = loadBeanDefinitions(resources);
            if (actualResources != null) {
                Collections.addAll(actualResources, resources);
            }
            if (logger.isTraceEnabled()) {
                logger.trace("Loaded " + count + " bean definitions from location pattern [" + location + "]");
            }
            return count;
        }
        catch (IOException ex) {
            throw new BeanDefinitionStoreException(
                    "Could not resolve bean definition resource pattern [" + location + "]", ex);
        }
    }
    else {
        // Can only load single resources by absolute URL.
        Resource resource = resourceLoader.getResource(location);
        int count = loadBeanDefinitions(resource);
        if (actualResources != null) {
            actualResources.add(resource);
        }
        if (logger.isTraceEnabled()) {
            logger.trace("Loaded " + count + " bean definitions from location [" + location + "]");
        }
        return count;
    }
}

// AbstractApplicationContext
public Resource[] getResources(String locationPattern) throws IOException {
    /*
    * resourcePatternResolver 之前就说过,是用来把配置文件从地址字符串读取成Resource的,Resource是计算机文件的抽象存在。
    *
    * getResources(locationPattern) 太细节了,考虑到篇幅长度这里就不跟了,简述一下跟踪步骤(如果使用的是示例项目的话)
    * PathMatchingResourcePatternResolver#getResources(String)  会进入 else 代码块里 else 代码块里
    *   DefaultResourceLoader#getResource(String) 会进入最下面的 catch 代码块里
    *       DefaultResourceLoader#getResourceByPath(String) 返回一个 ClassPathContextResource 类型的对象实例
    */
    return this.resourcePatternResolver.getResources(locationPattern);
}

// AbstractBeanDefinitionReader
public int loadBeanDefinitions(Resource... resources) throws BeanDefinitionStoreException {
    Assert.notNull(resources, "Resource array must not be null");
    int count = 0;
    for (Resource resource : resources) {
        count += loadBeanDefinitions(resource);
    }
    return count;
}

// XmlBeanDefinitionReader
public int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException {
    return loadBeanDefinitions(new EncodedResource(resource));
}

// XmlBeanDefinitionReader
public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException {
    Assert.notNull(encodedResource, "EncodedResource must not be null");
    if (logger.isTraceEnabled()) {
        logger.trace("Loading XML bean definitions from " + encodedResource);
    }

    // ---------------------------------- 将要解析的Resource放到线程本地中 --------------------------------

    Set currentResources = this.resourcesCurrentlyBeingLoaded.get();
    if (currentResources == null) {
        currentResources = new HashSet<>(4);
        this.resourcesCurrentlyBeingLoaded.set(currentResources); // 因为对Set的操作是引用操作,这里直接存就行
    }

    // ------------------------------------ 检测配置文件的循环依赖 -----------------------------------------

    if (!currentResources.add(encodedResource)) { // HashSet#add(Object)返回值表示的是:之前集合中是否存在相同元素
        // 这里抛出 配置文件循环加载 的异常提示,在 xml 配置中代表 
        throw new BeanDefinitionStoreException(
                "Detected cyclic loading of " + encodedResource + " - check your import definitions!");
    }
    try {
        // --------------------------------------- 对I/O的操作 --------------------------------------------

        InputStream inputStream = encodedResource.getResource().getInputStream();
        try {
            InputSource inputSource = new InputSource(inputStream);
            if (encodedResource.getEncoding() != null) {
                inputSource.setEncoding(encodedResource.getEncoding());
            }

            // ----------------------------------- 解析配置文件 --------------------------------------------

            // 返回值代表这一次调用注册了多少个 BeanDefinition
            return doLoadBeanDefinitions(inputSource, encodedResource.getResource());
        }
        finally {
            inputStream.close();
        }
    }
    catch (IOException ex) {
        throw new BeanDefinitionStoreException(
                "IOException parsing XML document from " + encodedResource.getResource(), ex);
    }
    finally {
        // 从线程本地存储的集合中删除当前 解析的Resource, 代表某个配置文件已经解析并且注册完成。
        currentResources.remove(encodedResource);
        if (currentResources.isEmpty()) {
            this.resourcesCurrentlyBeingLoaded.remove(); // 代表所有的配置文件全部处理完成
        }
    }
}

到这里,各种各样的loadBeanDefinitions方法调用就到头了,它们都是讲数据类型转来转去传来传去的,没有真正的进行解析和注册工作。
doLoadBeanDefinitions方法中就要开始真正的解析配置文件并注册BeanDefinition了。

// XmlBeanDefinitionReader
protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
        throws BeanDefinitionStoreException {

    try {
        // 把文件读成 Document 对象,其中有对之前传入的 EntityResolver 对象的使用
        Document doc = doLoadDocument(inputSource, resource);
        // 注册解析到的 BeanDefinition 到 IOC 容器中,返回值代表这一次调用注册了多少个 BeanDefinition
        int count = registerBeanDefinitions(doc, resource);
        if (logger.isDebugEnabled()) {
            logger.debug("Loaded " + count + " bean definitions from " + resource);
        }
        return count;
    }
    // ... 省略了一大批 catch 代码块
}

// XmlBeanDefinitionReader
public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
    // 这里返回的是 DefaultBeanDefinitionDocumentReader 类的实例对象。
    BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
    // 从IOC容器中获取到之前注册的 BeanDefinition 的数量
    int countBefore = getRegistry().getBeanDefinitionCount();

    documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
    // 计算出这次注册了多少个 BeanDefinition
    return getRegistry().getBeanDefinitionCount() - countBefore;
}

// XmlBeanDefinitionReader
public XmlReaderContext createReaderContext(Resource resource) {
    // 传入的这个 this 很关键
    // getNamespaceHandlerResolver() 不做跟踪,返回的是 DefaultNamespaceHandlerResolver 类的实例对象
    return new XmlReaderContext(resource, this.problemReporter, this.eventListener,
            this.sourceExtractor, this, getNamespaceHandlerResolver());
}

// DefaultBeanDefinitionDocumentReader
public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
    this.readerContext = readerContext;
    doRegisterBeanDefinitions(doc.getDocumentElement());
}

// DefaultBeanDefinitionDocumentReader
protected void doRegisterBeanDefinitions(Element root) {
    // ... 省略了解析配置文件的代码

    preProcessXml(root); // 一个空Hook
    parseBeanDefinitions(root, this.delegate);
    postProcessXml(root); // 一个空Hook

    // ...
}

// DefaultBeanDefinitionDocumentReader
protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
    // 如果根节点的命名空间是 http://www.springframework.org/schema/beans,那么会进入 if 代码块
    // 也就是对 主命名空间/默认命名空间 的确认,如果不了解什么是命名空间的可以看 https://www.w3school.com.cn/tags/tag_prop_xmlns.asp
    if (delegate.isDefaultNamespace(root)) {
        // ... 省略了部分嵌套逻辑
        if (delegate.isDefaultNamespace(ele)) { // 如果当前节点使用的是默认命名空间
            //  标签使用的就是默认命名空间
            parseDefaultElement(ele, delegate);
        }
        else {
            //  这些它们使用的是各自的命名空间,分别是context和aop
            // 这种的就会进入这里,关于这些的之后有空再具体跟,现阶段Spring的基础流程才是目的。
            delegate.parseCustomElement(ele);
        }
        // ... 省略了部分嵌套逻辑
    }
    else {
        // 根节点主命名空间是其它的情况,这里不考虑会进入这个方法,如果你自定义了主命名空间可以看看。
        delegate.parseCustomElement(root);
    }
}

// DefaultBeanDefinitionDocumentReader
private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
    if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) { // 处理  标签的
        importBeanDefinitionResource(ele);
    }
    else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) { // 处理  标签的
        processAliasRegistration(ele);
    }
    else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) { // 处理  标签的
        processBeanDefinition(ele, delegate);
    }
    else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) { // 处理  标签的
        // recurse
        doRegisterBeanDefinitions(ele);
    }
}

// DefaultBeanDefinitionDocumentReader
protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
    // ---------------------------------------- 解析配置文件 ----------------------------------------

    // 把  标签 解析成 BeanDefinitionHolder 对象实例,BeanDefinitionHolder 内部持有 BeanDefinition。
    // 想具体了解就看 DefaultBeanDefinitionDocumentReader#parseBeanDefinitionElement(Element, BeanDefinition)
    BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
    if (bdHolder != null) {
        // 使用装饰者模式,对BeanDefinition进行装饰,实际上是解析自定义的元素,主要是两个操作
        // 1.Decorate based on custom attributes first. (首先基于自定义的标签属性进行装饰)
        // 2.Decorate based on custom nested elements. (然后基于自定义的子标签进行装饰)
        bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
        try {
            // --------------------------------- 注册BeanDefinition ------------------------------

            // 第一个参数是持有目标 BeanDefinition 的 BeanDefinitionHolder
            // 第二个参数是 IOC容器,这个之前在 XmlBeanDefinitionReader#createReaderContext(Resource) 传进来的,上面有
            BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
        }
        catch (BeanDefinitionStoreException ex) {
            getReaderContext().error("Failed to register bean definition with name '" +
                    bdHolder.getBeanName() + "'", ele, ex);
        }
        // ------------------------------------ 发送BeanDefinition注册完成的事件 ----------------------

        // 发送注册事件,也是 XmlBeanDefinitionReader#createReaderContext(Resource) 传进来的。
        // 默认情况下这个事件什么都不做,可以通过手动在 XmlBeanDefinitionReader 中配置。
        getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
    }
}

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

    // -------------------------- 注册BeanDefinition ---------------------------------

    // Register bean definition under primary name.
    String beanName = definitionHolder.getBeanName();
    // 不再深入,想看可以去 DefaultListableBeanFactory#registerBeanDefinition
    registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());

    // ------------------------------- 注册别名 ------------------------------------

    // Register aliases for bean name, if any.
    String[] aliases = definitionHolder.getAliases();
    if (aliases != null) {
        for (String alias : aliases) {
            registry.registerAlias(beanName, alias);
        }
    }
}

1.2.3. prepareBeanFactory

protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
    // Tell the internal bean factory to use the context's class loader etc.
    beanFactory.setBeanClassLoader(getClassLoader());
    // BeanExpressionResolver 这个和 Spring表达式语言SpEL 有关
    beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
    beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));

    // Configure the bean factory with context callbacks.
    beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));  // 添加 BeanPostProcessor

    // ------------------------------------- 设置忽略注入的接口 -------------------------------------
    // 这些会在DependencyCheck的处理逻辑中使用到
    beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
    beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
    beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
    beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
    beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
    beanFactory.ignoreDependencyInterface(ApplicationContextAware.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);

    // Register early post-processor for detecting inner beans as ApplicationListeners.
    beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));  // 添加 BeanPostProcessor

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

1.2.4. postProcessBeanFactory(调用使用者在子类中自定义的内部容器的后处理)

在执行这一步时,所有的BeanDefinition已经被加载完成,但还没有Bean被实例化。
这一步就是允许在ApplicationContext的子类中进行对内部IOC容器的后处理,允许使用者在BeanDefinition加载完成之后,在Bean实例化之前对内部IOC容器做一些自定义的修改行为。
默认情况下,是一个空的实现,可以在子类内重写这个方法。

下面用一个示例展示 postProcessBeanFactory 的使用方式。

// 配置文件

    
    



现在我们要通过重写postProcessBeanFactory方法,在它的过程内,变更配置文件里面设置的content的值。

// 程序入口
public static void main(String[] args) {
    ApplicationContext ac = new MyClassPathXmlApplicationContext(new String[]{"spring-config.xml"}, true, null);
}

class MyClassPathXmlApplicationContext extends ClassPathXmlApplicationContext {
    public MyClassPathXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent) throws BeansException {
        super(configLocations, refresh, parent);
    }

    @Override
    protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
        // 这里已经获取到了 内部IOC容器,很多行为都是可以展开的。

        BeanDefinition helloService = beanFactory.getBeanDefinition("helloService");
        helloService.getPropertyValues().addPropertyValue("content", "world");
    }
}

1.2.5. invokeBeanFactoryPostProcessors

对多种形式产生的BeanFactoryPostProcessor进行postProcessBeanFactory方法的调用。
代码内涉及两类BeanFactoryPostProcessor:
一类是实现了BeanFactoryPostProcessor接口的
一类是实现了BeanDefinitionRegistryPostProcessor接口的

BeanDefinitionRegistryPostProcessor接口继承自BeanFactoryPostProcessor接口
当使用者尝试自定义一个BeanDefinitionRegistryPostProcessor接口的实现类时需要重写两个方法
1.postProcessBeanFactory(ConfigurableListableBeanFactory)
2.postProcessBeanDefinitionRegistry(BeanDefinitionRegistry) 建议只用来进行 BeanDefinition 的注册管理工作。
这里的这个postProcessBeanFactory方法AbstractApplicationContext#refresh()里直接调用的postProcessBeanFactory方法作用差不多,
只不过是使用方式和调用时机有些不同。

// AbstractApplicationContext
protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
    PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());

    // Detect a LoadTimeWeaver and prepare for weaving, if found in the meantime
    // (e.g. through an @Bean method registered by ConfigurationClassPostProcessor)
    if (beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
        beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
        beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
    }
}

// AbstractApplicationContext
public List getBeanFactoryPostProcessors() {
    // 可以通过 ConfigurableApplicationContext#addBeanFactoryPostProcessor 方法来添加内部IOC容器的后处理器,下面有展示
    // 默认情况下这里是没有值的,Spring Boot框架中这里会传递一些值。
    return this.beanFactoryPostProcessors;
}

// PostProcessorRegistrationDelegate
public static void invokeBeanFactoryPostProcessors(
        ConfigurableListableBeanFactory beanFactory, List beanFactoryPostProcessors) {

    // Invoke BeanDefinitionRegistryPostProcessors first, if any.
    Set processedBeans = new HashSet<>(); // 存放的是 受内部IOC容器管理的 且 已被实例化过后的 BeanDefinitionRegistryPostProcessor

    // 之前的逻辑里面可以知道内部容器是 DefaultListableBeanFactory 实现,通过它的类结构图可以看出来会进入下面这个 if 代码块
    // IOC 容器继承自 BeanDefinitionRegistry 代表了什么? 代表了它内部可以管理 BeanDefinition 的注册等行为。
    if (beanFactory instanceof BeanDefinitionRegistry) {
        BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;

        // 注意一下这两个集合的泛型类型。
        List regularPostProcessors = new ArrayList<>(); // 存储常规的BeanFactory后处理器(也就是实现了BeanFactoryPostProcessor接口的)
        List registryProcessors = new ArrayList<>(); // 存储所有 BeanDefinitionRegistryPostProcessor (被/不被容器管理的都在里面)

        // ------------------------------------------------------- 处理没有被内部IOC容器管理的 BeanFactoryPostProcessor -------------------------------------------

        for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
            if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
                BeanDefinitionRegistryPostProcessor registryProcessor =
                        (BeanDefinitionRegistryPostProcessor) postProcessor;
                registryProcessor.postProcessBeanDefinitionRegistry(registry);
                registryProcessors.add(registryProcessor);
            }
            else {
                regularPostProcessors.add(postProcessor);
            }
        }

        // ------------------------------------------------------- 处理内部IOC容器管理的 BeanDefinitionRegistryPostProcessor -------------------------------------------
        // 在处理之前,它们都还是 BeanDefinition

        /*
        * 下面会出现3段极其相似的代码,目的是对 实现了PriorityOrdered 和 实现了Ordered 的 BeanDefinitionRegistryPostProcessor
        * 进行区别对待,各自进行各自的排序。
        */

        List currentRegistryProcessors = new ArrayList<>(); // 存储受IOC容器管理的 BeanDefinitionRegistryPostProcessor

        /*
        * 第一段相似代码
        * 
        * 从内部IOC容器中找到实现了 PriorityOrdered 的 BeanDefinitionRegistryPostProcessor,
        * 然后调用 beanFactory.getBean 把它们进行实例化(这时候它们就从BeanDefinition变成Bean了)
        * 
        * 关于调用 beanFactory.getBean 可以是 BeanDefinition变成Bean 的逻辑之后再说。
        */

        String[] postProcessorNames =
                beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
        for (String ppName : postProcessorNames) {
            if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
                currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
                processedBeans.add(ppName);
            }
        }
        sortPostProcessors(currentRegistryProcessors, beanFactory); // 简单排序
        registryProcessors.addAll(currentRegistryProcessors); // 简单合并集合
        invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry); // 批量调用 postProcessBeanDefinitionRegistry 方法
        currentRegistryProcessors.clear(); // 简单清除

        // ---- 从内部IOC容器中找到实现了 Ordered 且 没有被上面处理过 的 BeanDefinitionRegistryPostProcessor 进行一样的处理过程
        // 第二段相似代码

        postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
        for (String ppName : postProcessorNames) {
            if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) {
                currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
                processedBeans.add(ppName);
            }
        }
        sortPostProcessors(currentRegistryProcessors, beanFactory);
        registryProcessors.addAll(currentRegistryProcessors);
        invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
        currentRegistryProcessors.clear();

        // ---- 从内部IOC容器中找到其它没有被上面处理过 的 BeanDefinitionRegistryPostProcessor 进行一样的处理过程
        // 第三段相似代码

        boolean reiterate = true;
        while (reiterate) {
            reiterate = false;
            postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
            for (String ppName : postProcessorNames) {
                if (!processedBeans.contains(ppName)) {
                    currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
                    processedBeans.add(ppName);
                    reiterate = true;
                }
            }
            sortPostProcessors(currentRegistryProcessors, beanFactory);
            registryProcessors.addAll(currentRegistryProcessors);
            invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
            currentRegistryProcessors.clear();
        }

        // --------------------------------- 调用到目前为止处理的所有BeanFactoryPostProcessor的postProcessBeanFactory方法 -------------------------------

        invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
        invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
    }

    else {
        // Invoke factory processors registered with the context instance.
        invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);
    }

    // ------------------------------------------------------- 处理内部IOC容器管理的 BeanFactoryPostProcessor -------------------------------------------
    // 在处理之前,它们都还是 BeanDefinition

    String[] postProcessorNames =
            beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);

    List priorityOrderedPostProcessors = new ArrayList<>(); // 存储实现了 PriorityOrdered 的 BeanFactoryPostProcessor
    List orderedPostProcessorNames = new ArrayList<>(); // 存储实现了 Ordered 的 BeanFactoryPostProcessor
    List nonOrderedPostProcessorNames = new ArrayList<>(); // 存储没有实现排序的 BeanFactoryPostProcessor
    for (String ppName : postProcessorNames) {
        if (processedBeans.contains(ppName)) { // 代表这个 BeanFactoryPostProcessor 已经被上面那段逻辑处理过了
            // skip - already processed in first phase above
        }
        else if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
            priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class)); // 获取到实例化后的Bean
        }
        else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
            orderedPostProcessorNames.add(ppName);
        }
        else {
            nonOrderedPostProcessorNames.add(ppName);
        }
    }

    // 对实现了 PriorityOrdered 的 BeanFactoryPostProcessor 进行一些操作

    sortPostProcessors(priorityOrderedPostProcessors, beanFactory); 
    invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);

    // 对实现了 Ordered 的 BeanFactoryPostProcessor 进行一些操作

    List orderedPostProcessors = new ArrayList<>();
    for (String postProcessorName : orderedPostProcessorNames) {
        orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class)); // 获取到实例化后的Bean
    }
    sortPostProcessors(orderedPostProcessors, beanFactory);
    invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);

    // 对没有实现排序的 BeanFactoryPostProcessor 进行一些操作

    List nonOrderedPostProcessors = new ArrayList<>();
    for (String postProcessorName : nonOrderedPostProcessorNames) {
        nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class)); // 获取到实例化后的Bean
    }
    invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);

    // Clear cached merged bean definitions since the post-processors might have
    // modified the original metadata, e.g. replacing placeholders in values... (清除已经缓存的合并的 BeanDefinition,因为 post-processors 可能修改了原始元数据(例如替换值中的占位符))
    beanFactory.clearMetadataCache();
}

1.2.5.1. BeanFactoryPostProcessor接口的使用示例

// 首先是创建两个实现类

class MyBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor {

    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {

    }

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {

    }
}

class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        
    }
}
下面展示两种形式的使用方式,实际上有多种方式能使用。
1.不受内部IOC容器管理
2.受内部IOC容器管理

// 第一种使用方式(不受内部IOC容器管理)
public class ApplicationContextTest {

    public static void main(String[] args) {
        ConfigurableApplicationContext ac = new ClassPathXmlApplicationContext(new String[]{"spring-config.xml"}, false, null);
        ac.addBeanFactoryPostProcessor(new MyBeanDefinitionRegistryPostProcessor());
        ac.addBeanFactoryPostProcessor(new MyBeanFactoryPostProcessor());
        ac.refresh();
    }
}

// 第二种使用方式(受内部IOC容器管理)

// spring-config.xml 配置文件



public class ApplicationContextTest {

    public static void main(String[] args) {
        ApplicationContext ac = new ClassPathXmlApplicationContext(new String[]{"spring-config.xml"}, true, null);
    }
}

1.2.6. registerBeanPostProcessors

主要工作内容:
1.从内部IOC容器中找到实现了BeanPostProcessor接口的BeanDefinition
2.全部进行Bean实例化,然后按照顺序添加到内部IOC容器的beanPostProcessors集合中。
3.额外添加了BeanPostProcessorCheckerApplicationListenerDetectord后处理器。
// todo: BeanPostProcessorChecker和ApplicationListenerDetector 要不要具体演示?

// AbstractApplicationContext
protected void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory) {
    PostProcessorRegistrationDelegate.registerBeanPostProcessors(beanFactory, this);
}

// PostProcessorRegistrationDelegate
public static void registerBeanPostProcessors(
        ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {
    /* 如果你使用的是示例项目, 调试的时候会看到这里有3个值
    * 1.org.springframework.context.annotation.internalAutowiredAnnotationProcessor  来源于对标签的解析,见ContextNamespaceHandler
    * 2.org.springframework.context.annotation.internalCommonAnnotationProcessor  来源于对标签的解析,见ContextNamespaceHandler
    * 3.org.springframework.aop.config.internalAutoProxyCreator  来源于对系列标签的解析,见AopNamespaceHandler
    * 它们都是 BeanDefinition 状态,它们也是在解析配置文件时被添加到容器内的
    */
    String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);

    // BeanPostProcessorChecker的作用是:当一个bean不适合被所有BeanPostProcessor处理时,它会记录一条信息
    int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length;    
    beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));

    // ----------------------------------------------------- 处理内部IOC容器管理的 BeanPostProcessor -------------------------------------------------
    // 在处理之前,它们都还是 BeanDefinition

    // 也是对实现PriorityOrdered、实现Ordered、不实现排序的进行分开处理

    List priorityOrderedPostProcessors = new ArrayList<>();
    List internalPostProcessors = new ArrayList<>(); // 存放的是一些Spring框架内部的 BeanPostProcessor
    List orderedPostProcessorNames = new ArrayList<>();
    List nonOrderedPostProcessorNames = new ArrayList<>();
    for (String ppName : postProcessorNames) {
        if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) { 
            BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class); // 获取到实例化后的Bean
            priorityOrderedPostProcessors.add(pp);
            if (pp instanceof MergedBeanDefinitionPostProcessor) {
                internalPostProcessors.add(pp);
            }
        }
        else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
            orderedPostProcessorNames.add(ppName);
        }
        else {
            nonOrderedPostProcessorNames.add(ppName);
        }
    }

    // ------------------------- 处理实现了PriorityOrdered的BeanPostProcessors -------------------------------

    sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
    registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors); // 把实例化的BeanPostProcessor放入内部IOC容器的beanPostProcessors集合中,下面的也都一样

    // --------------------------- 处理实现了Ordered的BeanPostProcessors -------------------------------

    List orderedPostProcessors = new ArrayList<>();
    for (String ppName : orderedPostProcessorNames) {
        BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class); // 获取到实例化后的Bean
        orderedPostProcessors.add(pp);
        if (pp instanceof MergedBeanDefinitionPostProcessor) {
            internalPostProcessors.add(pp);
        }
    }
    sortPostProcessors(orderedPostProcessors, beanFactory);
    registerBeanPostProcessors(beanFactory, orderedPostProcessors); 

    // --------------------------- 处理剩下的的BeanPostProcessors -------------------------------

    List nonOrderedPostProcessors = new ArrayList<>();
    for (String ppName : nonOrderedPostProcessorNames) {
        BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class); // 获取到实例化后的Bean
        nonOrderedPostProcessors.add(pp);
        if (pp instanceof MergedBeanDefinitionPostProcessor) {
            internalPostProcessors.add(pp);
        }
    }
    registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors);

    // --------------------------- 重新注册所有框架内部的BeanPostProcessor -----------------------------
    // 重复注册只是改变BeanPostProcessor在链中的位置,不会造成重复出现的。

    sortPostProcessors(internalPostProcessors, beanFactory);
    registerBeanPostProcessors(beanFactory, internalPostProcessors);

    // Re-register post-processor for detecting inner beans as ApplicationListeners,
    // moving it to the end of the processor chain (for picking up proxies etc).
    // (把用于检测内部Bean的后处理器重新注册为ApplicationListeners,将其移动到后处理器链的末端(用于获取代理等操作))。

    // ApplicationListenerDetector 用于检测那些实现了 ApplicationListener 接口的单例 bean,并且将它们放到 ApplicationContext 容器的监听器列表内。
    // 如果有事件多播器,也同时放到多播器里面。
    beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext));
}

1.2.7. initMessageSource

这一步的逻辑很简单,主要是对MessageSource的处理。
MessageSource用于解析消息的策略接口,支持此类消息的参数化和国际化,可以配合Spring MVC中的LocaleResolver使用。

public static final String MESSAGE_SOURCE_BEAN_NAME = "messageSource";

protected void initMessageSource() {
    ConfigurableListableBeanFactory beanFactory = getBeanFactory();
    // 如果内部IOC容器中,不管任何形式存在这个东西,就会进入到 if 代码块
    if (beanFactory.containsLocalBean(MESSAGE_SOURCE_BEAN_NAME)) {
        this.messageSource = beanFactory.getBean(MESSAGE_SOURCE_BEAN_NAME, MessageSource.class); // 获取到实例化后的Bean
        
        // 设置上下级关系
        if (this.parent != null && this.messageSource instanceof HierarchicalMessageSource) {
            HierarchicalMessageSource hms = (HierarchicalMessageSource) this.messageSource;
            if (hms.getParentMessageSource() == null) {
                // Only set parent context as parent MessageSource if no parent MessageSource
                // registered already.
                hms.setParentMessageSource(getInternalParentMessageSource());
            }
        }
        // ... 日志输出
    }
    else {
        // Use empty MessageSource to be able to accept getMessage calls.
        DelegatingMessageSource dms = new DelegatingMessageSource(); // 这实际上是个空壳,只是为了能够完成getMessage方法调用而提供的
        dms.setParentMessageSource(getInternalParentMessageSource());
        this.messageSource = dms;
        beanFactory.registerSingleton(MESSAGE_SOURCE_BEAN_NAME, this.messageSource);
        // ... 日志输出
    }
}

它的这部分处理代码很简单,没什么好说的,下面展示一下使用,示例项目中有提供代码。

// 这是启动类的代码
public static void main(String[] args) {
    ApplicationContext ac = new ClassPathXmlApplicationContext(new String[]{"spring-config.xml"}, true, null);

    TestService testService = ac.getBean("testService", TestService.class);
    testService.test();
}

// 这是使用的代码
@Service
public class TestService {
    @Autowired
    private MessageSource messageSource;

    public void test() {
        System.out.println(messageSource.getMessage("message.key.hello", null, Locale.CHINESE));
        System.out.println(messageSource.getMessage("message.key.hello", null, Locale.ENGLISH));
        System.out.println("invoke test");
    }
}

// 这是配置文件内的代码

    
    


在 resources/i18n/messages_en.properties 里面有这段代码
message.key.hello=hello
在 resources/i18n/messages_zh.properties 里面有这段代码
message.key.hello=你好

1.2.8. initApplicationEventMulticaster(初始化事件多播器)

这一步的逻辑跟很initMessageSource一样简单,主要是对ApplicationEventMulticaster的处理。
ApplicationEventMulticaster用于向ApplicationListener对象发布事件。

protected void initApplicationEventMulticaster() {
    ConfigurableListableBeanFactory beanFactory = getBeanFactory();
    if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) {
        this.applicationEventMulticaster =
                beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class);
        // ... 日志输出
    }
    else {
        this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
        beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster);
        // ... 日志输出
    }
}

1.2.9. onRefresh

这是个Hook方法,就像postProcessBeanFactory方法一样,需要ApplicationContext的子容器来自行实现。

onRefresh()方法调用之前,Spring主要完成了
内部IOC容器的创建和对配置文件的解析
BeanFactoryPostProcessor的处理
BeanPostProcessor的处理
MessageSource的实例化
ApplicationEventMulticaster的实例化

onRefresh()方法调用之后
注册监听器,发布早期事件
对non-lazy-init的bean进行初始化
收尾工作

在Spring Boot框架内,如果是默认的项目配置,那么会创建一个AnnotationConfigServletWebServerApplicationContext类型的IOC容器,在它的父类ServletWebServerApplicationContext中有对onRefresh()方法的重写。
通过查看代码可以看到,内部是对Servlet容器的创建,见ServletWebServerFactory#getWebServer
目前Spring Boot支持三种Servlet容器:1.Tomcat 2.Jetty 3.Undertow

1.2.10 registerListeners

主要做了两件事
1.注册所有受/不受内部IOC容器管理的ApplicationListener
2.通过多播器将earlyApplicationEvents集合中存储的事件全部发布出去。
多播器的初始化见initApplicationEventMulticaster()

protected void registerListeners() {
    // ---------------------------------------- 处理不受内部IOC容器管理的 ApplicationListener --------------------------------------------

    // getApplicationListeners() 获取到是不受内部IOC容器管理的ApplicationListener集合,可以通过手动配置
    for (ApplicationListener listener : getApplicationListeners()) {
        getApplicationEventMulticaster().addApplicationListener(listener); // 将ApplicationListener全部添加到事件多播器中。
    }

    // ----------------------------------------- 处理受内部IOC容器管理的 ApplicationListener --------------------------------------------

    String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
    for (String listenerBeanName : listenerBeanNames) {
        getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName); // 添加到事件多播器中
    }

    // --------------------------------------------- 发布之前堆积的 ApplicationEvent ---------------------------------------------------

    // 在之前`prepareRefresh`方法中创建了earlyApplicationEvents集合,由于之前IOC容器中没有多播器,所以之前发布的事件都会存放在这个集合中
    // 现在我们有了多播器(在initApplicationEventMulticaster()方法中创建了一个),只需要将堆积的事件通过多播器发布出去就行了。

    Set earlyEventsToProcess = this.earlyApplicationEvents;
    this.earlyApplicationEvents = null;
    if (earlyEventsToProcess != null) {
        for (ApplicationEvent earlyEvent : earlyEventsToProcess) {
            getApplicationEventMulticaster().multicastEvent(earlyEvent);
        }
    }
}

这里展示一下如何注册不受内部IOC容器管理的ApplicationListener,并让它们起作用。

// 这里不能使用 ApplicationContext 作为父类引用,使用 ClassPathXmlApplicationContext 或者 ConfigurableApplicationContext 这些都行。
public static void main(String[] args) {
    // 要把构造函数内的 refresh 设置为 false,然后手动刷新。
    ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext(new String[]{"spring-config.xml"}, false, null);
    ac.addApplicationListener(event -> {});
    ac.refresh(); // 手动刷新
}

1.2.11. finishBeanFactoryInitialization

protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
    // ---------------------------------------------- 为当前IOC容器初始化一个 ConversionService ------------------------------------

    // 初始化一个 ConversionService 并且设置给内部IOC容器 (前提是有的话)
    // ConversionService 是一个用于类型转换的服务接口。 调用 convert(Object,Class) 以使用此系统执行线程安全类型转换。

    if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) &&
            beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {
        beanFactory.setConversionService(
                beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));
    }

    // ---------------------------------------------- 处理IOC容器中的嵌入式值解析器 ---------------------------------------------------

    // 如果当前的IOC容器中没有嵌入式值解析器就添加一个默认的StringValueResolver
    // 这个默认的嵌入式值解析器会试图从当前环境根据传入的key解析出来一个值,

    if (!beanFactory.hasEmbeddedValueResolver()) {
        beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal));
    }

    // ---------------------------------------------- 处理 LoadTimeWeaverAware ------------------------------------------------------

    // Initialize LoadTimeWeaverAware beans early to allow for registering their transformers early. (尽早初始化LoadTimeWeaverAware,以便尽早注册它们的转换器。)
    String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
    for (String weaverAwareName : weaverAwareNames) {
        getBean(weaverAwareName); // 获取到实例化后的Bean
    }

    // ---------------------------------------------- 对内部IOC容器的一些属性设置 -----------------------------------------------------

    // Stop using the temporary ClassLoader for type matching. (停止使用临时类加载器进行类型匹配。)
    beanFactory.setTempClassLoader(null);

    // 冻结BeanDefinition的元数据,不再期待进一步的处理
    beanFactory.freezeConfiguration();

    // 实例化剩下的 non-lazy-init 的 bean
    beanFactory.preInstantiateSingletons();
}

// DefaultListableBeanFactory
public void preInstantiateSingletons() throws BeansException {
    // ... 日志打印

    // Iterate over a copy to allow for init methods which in turn register new bean definitions.
    // While this may not be part of the regular factory bootstrap, it does otherwise work fine.
    List beanNames = new ArrayList<>(this.beanDefinitionNames);

    // ------------------------------------------------- 初始化所有不是懒加载的bean ----------------------------------------------------

    for (String beanName : beanNames) {
        RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
        if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) { // 如果不是抽象的,是单例的,不是懒加载的

            if (isFactoryBean(beanName)) {
                // ------------------------------------- 对FactoryBean的处理 -----------------------------------------
                // 普通的Bean的初始化行为会交由容器完成,是使用者无法控制的。
                // FactoryBean的初始化行为则是交由类本身完成,是使用者可以自定义的。

                Object bean = getBean(FACTORY_BEAN_PREFIX + beanName); // IOC容器对实现了FactoryBean接口的类会区别对待,方式就是在名字前加个&符号
                if (bean instanceof FactoryBean) {
                    final FactoryBean factory = (FactoryBean) bean;

                    /*
                    * 首先判断是否实现了 SmartFactoryBean,如果实现了那就再判断 FactoryBean 是否是迫切加载的。
                    * SmartFactoryBean 是 FactoryBean 的子接口,内部额外提供了isPrototype和isEagerInit两个方法。
                    */
                    boolean isEagerInit;
                    if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
                        isEagerInit = AccessController.doPrivileged((PrivilegedAction)
                                        ((SmartFactoryBean) factory)::isEagerInit,
                                getAccessControlContext());
                    }
                    else {
                        isEagerInit = (factory instanceof SmartFactoryBean &&
                                ((SmartFactoryBean) factory).isEagerInit());
                    }
                    // 如果 FactoryBean 明确指出是迫切加载的,则立刻执行Bean初始化操作
                    if (isEagerInit) {
                        getBean(beanName);
                    }
                }
            }
            else {
                // ------------------------------------- 对普通Bean的处理 -----------------------------------------

                getBean(beanName);
            }
        }
    }

    // ------------------------------------ 调用实现了SmartInitializingSingleton接口的单例bean的afterSingletonsInstantiated方法 -------------------------------------

    // Trigger post-initialization callback for all applicable beans...
    for (String beanName : beanNames) {
        Object singletonInstance = getSingleton(beanName);
        if (singletonInstance instanceof SmartInitializingSingleton) {
            final SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
            if (System.getSecurityManager() != null) {
                AccessController.doPrivileged((PrivilegedAction) () -> {
                    smartSingleton.afterSingletonsInstantiated();
                    return null;
                }, getAccessControlContext());
            }
            else {
                smartSingleton.afterSingletonsInstantiated();
            }
        }
    }
}
 
 

1.2.11.1. 嵌入式值解析器的使用

// 这里不能使用 ApplicationContext 作为父类引用,使用 ClassPathXmlApplicationContext 或者 ConfigurableApplicationContext 这些都行。

public static void main(String[] args) {
    ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext(new String[]{"spring-config.xml"}, true, null);
    // 使用时要加上占位符
    System.out.println(ac.getBeanFactory().resolveEmbeddedValue("${JAVA_HOME}"));
}

1.2.11.2. LoadTimeWeaver

LoadTimeWeaver 官方文档
Spring之LoadTimeWeaver——一个需求引发的思考
使用AspectJ LTW(Load Time Weaving)
代码织入(Weaving),指将切面代码插入到目标地方的过程,有3种方式(编译时织入-CTW、类加载时织入-LTW、运行时织入-RTW)。
在Spring中,也有提供了对LTW的支持,更多有关Spring LTW的内容点击此处查看。

CTW:在类的编译期,采用特殊的编译器,来织入切面
LTW:通过特殊的类加载器,在类加载到JVM时,替换字节码,来织入切面
RTW:采用CGLib或JDK动态代理进行切面的织入

框架名     CTW     LTW     RTW
AspectJ 支持      支持      不支持
Spring  不支持 支持      支持

1.2.11.3. FactoryBean 和 SmartFactoryBean 的使用示例

// FactoryBean 的使用示例

// 配置文件


// 自定义一个 FactoryBean
public class MyFactoryBean implements FactoryBean {
    @Override
    public MyFactoryBean getObject() throws Exception {
        return new MyFactoryBean();
    }

    @Override
    public Class getObjectType() {
        return MyFactoryBean.class;
    }

    @Override
    public boolean isSingleton() { // 接口中是有默认值的,默认为true
        return true;
    }
}

SmartFactoryBeanFactoryBean 的子接口,内部多了两个有默认值的方法(在JDK 1.8里),分别是
isPrototype()默认值是false,表示是否是多例;
isEagerInit()默认值是false,表示是否是迫切加载;

1.2.11.4. SmartInitializingSingleton的使用示例

@Service
public class TestService implements SmartInitializingSingleton {
    @Override
    public void afterSingletonsInstantiated() {
        
    }
}

1.2.11.5. AccessController

Java 安全模型介绍

// 在上文中可以看到这样一段代码

isEagerInit = AccessController
        .doPrivileged(
                (PrivilegedAction)((SmartFactoryBean) factory)::isEagerInit, 
                getAccessControlContext()
        );
// 这是最简形式

PrivilegedAction action = () -> null;
AccessController.doPrivileged(action, null)
 
 

如果已经阅读过上面那篇文章,就应该知道这样的一段代码表达的含义:让action这一段受信任代码获得更大的权限。

1.2.12. finishRefresh

protected void finishRefresh() {
    // ------------------------------------------------------ 清除 Resource 缓存 -------------------------------------------------------
    // 什么时候缓存的? 上面说了有个步骤会调用 DefaultResourceLoader#getResource(String) 里最下面的catch代码块,就是那行代码,因为太细节所以上文没说。

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

    // ------------------------------------------------------ 初始化 LifecycleProcessor ----------------------------------------------

    // Initialize lifecycle processor for this context.
    initLifecycleProcessor();

    // -------------------------------------------- 触发 LifecycleProcessor 的 onRefresh 方法 -----------------------------------------

    // Propagate refresh to lifecycle processor first.
    getLifecycleProcessor().onRefresh();

    // ----------------------------------------------------- 发布 ContextRefreshedEvent 事件 ------------------------------------------

    // Publish the final event.
    publishEvent(new ContextRefreshedEvent(this));

    // ------------------------------------------------------ JMX的逻辑 ------------------------------------------------------------

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

1.2.12.1. initLifecycleProcessor

这一步的逻辑跟很initMessageSource一样简单,主要是对initLifecycleProcessor的处理。
LifecycleProcessor的主要作用是控制BeanFactory中的所有实现Lifecycle的单例bean的启动/停止。

protected void initLifecycleProcessor() {
    ConfigurableListableBeanFactory beanFactory = getBeanFactory();
    if (beanFactory.containsLocalBean(LIFECYCLE_PROCESSOR_BEAN_NAME)) {
        this.lifecycleProcessor =
                beanFactory.getBean(LIFECYCLE_PROCESSOR_BEAN_NAME, LifecycleProcessor.class);
        // ... 日志打印
    }
    else {
        DefaultLifecycleProcessor defaultProcessor = new DefaultLifecycleProcessor();
        defaultProcessor.setBeanFactory(beanFactory);
        this.lifecycleProcessor = defaultProcessor;
        beanFactory.registerSingleton(LIFECYCLE_PROCESSOR_BEAN_NAME, this.lifecycleProcessor);
        // ... 日志打印
    }
}

1.2.12.2. LiveBeansView

这个东西和JMX有关,是Spring在这一方面的实现,看不看都行。

在 Java 程序的运行过程中,对 JVM 和系统的监测一直是 Java 开发人员在开发过程所需要的。一直以来,Java 开发人员必须通过一些底层的 JVM API,比如 JVMPI 和 JVMTI 等,才能监测 Java 程序运行过程中的 JVM 和系统的一系列情况,这种方式一直以来被人所诟病,因为这需要大量的 C 程序和 JNI 调用,开发效率十分低下。于是出现了各种不同的专门做资源管理的程序包。为了解决这个问题,Sun 公司也在其 Java SE 5 版本中,正式提出了 Java 管理扩展(Java Management Extensions,JMX)用来管理检测 Java 程序(同时 JMX 也在 J2EE 1.4 中被发布)。

JMX 的提出,让 JDK 中开发自检测程序成为可能,也提供了大量轻量级的检测 JVM 和运行中对象 / 线程的方式,从而提高了 Java 语言自己的管理监测能力。

JMX 与系统管理

如果你已经看过上面的文档,你大概对JMX是什么以及怎么用有了一点了解,回头看Spring的LiveBeansView就知道他在干什么了

public class LiveBeansView implements LiveBeansViewMBean, ApplicationContextAware
// ...


public interface LiveBeansViewMBean {
    String getSnapshotAsJson();
}

你可能感兴趣的:(Spring 源码阅读-IOC容器的启动过程)