(二)源码导读-Spring容器初始化流程-ApplicationContext

✨这里是第七人格的博客✨小七,欢迎您的到来~✨

🍅系列专栏:源码解析🍅

✈️本篇内容: 源码导读-Spring容器初始化流程-ApplicationContext✈️

🍱 本篇收录完整代码地址:gitee.com/diqirenge/s... 🍱

楔子

ApplicationContext在BeanFactory的基础上,拓展了非常多的高级特性,我们在实际的业务开发中ApplicationContext也相对用的更多,上一章我们讲了XmlBeanFactory中bean的初始化流程,这一章小七就和大家再一起看看ClassPathXmlApplicationContext中bean的初始化流程。

使用示例

首先在BeanFactoryDemo,使用ClassPathXmlApplicationContext

java 复制代码
/**
 * Spring 简单使用示例
 * 关注公众号【奔跑的码畜】,一起进步不迷路
 *
 * @author 第七人格
 * @date 2024/01/25
 */
public class BeanFactoryDemo {

    private static final String FILE_NAME = "spring.xml";

    public static void main(String[] args) {
        // 测试ClassPathXmlApplicationContext
        ClassPathXmlApplicationContext demo = createApplicationContext(FILE_NAME);
        MyBean myBean = (MyBean) demo.getBean("myBean");
        System.out.println(myBean.getName());
    }


    public  static ClassPathXmlApplicationContext createApplicationContext(String fileName) throws BeansException {
        return new ClassPathXmlApplicationContext(fileName);
    }


}

执行main方法输出结果

myName

从ClassPathXmlApplicationContext构造方法开始分析

java 复制代码
public ClassPathXmlApplicationContext(String configLocation) throws BeansException {
    this(new String[] {configLocation}, true, null);
}
java 复制代码
public ClassPathXmlApplicationContext(
       String[] configLocations, boolean refresh, @Nullable ApplicationContext parent)
       throws BeansException {
	// 第一步
    super(parent);
    // 第二步
    setConfigLocations(configLocations);
    if (refresh) {
        // 第三步
       refresh();
    }
}

第一步:分析父类的构造方法

首先我们分析一下,第一步的构造方法干了啥。

跟进super(parent);这个方法,我们发现和分析XmlBeanFactory的时候一样,又是漫长的找爸爸~

最后我们来到了AbstractApplicationContext

java 复制代码
public AbstractApplicationContext(@Nullable ApplicationContext parent) {
    this();
    setParent(parent);
}

看看和以前分析的XmlBeanFactory,你说像不像O(∩_∩)O哈哈~

java 复制代码
public AbstractAutowireCapableBeanFactory(@Nullable BeanFactory parentBeanFactory) {
    this();
    setParentBeanFactory(parentBeanFactory);
}

好了,继续分析AbstractApplicationContext的this方法

java 复制代码
public AbstractApplicationContext() {
    this.resourcePatternResolver = getResourcePatternResolver();
}

这个构造方法调用了getResourcePatternResolver方法,为resourcePatternResolver赋值,而resourcePatternResolver是个什么东西呢?我们点进去瞟一眼。

原来是个Resource啊。当然Resource是个接口,我们可以再通过getResourcePatternResolver方法知道,他具体返回的是一个PathMatchingResourcePatternResolver的对象

java 复制代码
protected ResourcePatternResolver getResourcePatternResolver() {
    return new PathMatchingResourcePatternResolver(this);
}

再看看setParent方法

java 复制代码
public void setParent(@Nullable ApplicationContext parent) {
    this.parent = parent;
    if (parent != null) {
       Environment parentEnvironment = parent.getEnvironment();
       if (parentEnvironment instanceof ConfigurableEnvironment) {
          getEnvironment().merge((ConfigurableEnvironment) parentEnvironment);
       }
    }
}

我们现在传入的parent是空的,所以这块代码就是把成员变量parent置为了空而已。

至此第一步分析完了,调用分类的构造方法,就是做了一些资源加载的工作。

第二步:setConfigLocations方法干了啥

接着看看第二步setConfigLocations方法干了啥

很明显resolvePath这个方法是主要方法,继续跟进去看看

翻译下resolveRequiredPlaceholders方法的注释:解析给定文本中的${...}占位符,用getProperty解析出的相应属性值替换它们。无法解析且没有默认值的占位符将导致抛出IllegalArgumentException异常。

第二步的作用也差不多看完了,但是好像还是没有看到bean初始化的关键代码,所以我们继续往下分析。

第三步:核心方法refresh

点进第三步refresh()方法

java 复制代码
public void refresh() throws BeansException, IllegalStateException {
    synchronized (this.startupShutdownMonitor) {
       // Prepare this context for refreshing.
       prepareRefresh();

       // Tell the subclass to refresh the internal bean factory.
       ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

       // Prepare the bean factory for use in this context.
       prepareBeanFactory(beanFactory);

       try {
          // Allows post-processing of the bean factory in context subclasses.
          postProcessBeanFactory(beanFactory);

          // Invoke factory processors registered as beans in the context.
          invokeBeanFactoryPostProcessors(beanFactory);

          // Register bean processors that intercept bean creation.
          registerBeanPostProcessors(beanFactory);

          // Initialize message source for this context.
          initMessageSource();

          // Initialize event multicaster for this context.
          initApplicationEventMulticaster();

          // Initialize other special beans in specific context subclasses.
          onRefresh();

          // Check for listener beans and register them.
          registerListeners();

          // Instantiate all remaining (non-lazy-init) singletons.
          finishBeanFactoryInitialization(beanFactory);

          // Last step: publish corresponding event.
          finishRefresh();
       }

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

          // Destroy already created singletons to avoid dangling resources.
          destroyBeans();

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

          // Propagate exception to caller.
          throw ex;
       }

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

看看这代码量,看看这注释,绝对是核心的核心啊(#^.^#)

1、初始化上下文信息

首先我们来看看prepareRefresh()这个方法,根据注释,我们知道他是在初始化上下文信息

java 复制代码
// Prepare this context for refreshing.
// 初始化上下文信息
prepareRefresh();

跟进去看看具体实现

java 复制代码
protected void prepareRefresh() {
    // Switch to active.
    // 设置容器初始化时间
    this.startupDate = System.currentTimeMillis();
    // 设置关闭状态为false
    this.closed.set(false);
    // 设置激活状态为true
    this.active.set(true);

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

    // Initialize any placeholder property sources in the context environment.
    // 初始化上下文环境中的任何占位符属性源
    initPropertySources();

    // Validate that all properties marked as required are resolvable:
    // see ConfigurablePropertyResolver#setRequiredProperties
    // 校验必填的属性值
    getEnvironment().validateRequiredProperties();

    // Store pre-refresh ApplicationListeners...
    // 存储预刷新应用程序监听器
    // 以下是关于事件和监听的代码,先插个眼,后面有用到再来看看
    if (this.earlyApplicationListeners == null) {
       this.earlyApplicationListeners = new LinkedHashSet<>(this.applicationListeners);
    }
    else {
       // Reset local application listeners to pre-refresh state.
       this.applicationListeners.clear();
       this.applicationListeners.addAll(this.earlyApplicationListeners);
    }

    // Allow for the collection of early ApplicationEvents,
    // to be published once the multicaster is available...
    this.earlyApplicationEvents = new LinkedHashSet<>();
}

他初始化了一些必要信息,其中initPropertySources方法是一个protected修饰的空方法,也就是说他也是Spring留给咱们的拓展点。

2、初始化BeanFactory

java 复制代码
   // Tell the subclass to refresh the internal bean factory.
   // 告诉子类刷新内部bean工厂 - 初始化BeanFactory
   ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

跟进obtainFreshBeanFactory方法

java 复制代码
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
    // 刷新bean工厂
    refreshBeanFactory();
    // 获取bean工厂
    return getBeanFactory();
}

我们可以看到逻辑还是比较清晰的,先刷新bean工厂,再获取bean工厂。

这里我们先看看他是如何刷新bean工厂的。跟进AbstractRefreshableApplicationContext#refreshBeanFactory()

java 复制代码
protected final void refreshBeanFactory() throws BeansException {
    // 判断bean是否存在
    // 我们第一次进来,bean肯定是不存在的
    if (hasBeanFactory()) {
       destroyBeans();
       closeBeanFactory();
    }
    try {
        // 创建bean工厂
       DefaultListableBeanFactory beanFactory = createBeanFactory();
        // 赋值序列化id
       beanFactory.setSerializationId(getId());
        // 自定义bean工厂
       customizeBeanFactory(beanFactory);
        // 载入bean定义
       loadBeanDefinitions(beanFactory);
        // 将创建好的bean工厂赋值给AbstractRefreshableApplicationContext的属性
       this.beanFactory = beanFactory;
    }
    catch (IOException ex) {
       throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
    }
}

跟进createBeanFactory方法,他其实就是new了一个DefaultListableBeanFactory对象,而DefaultListableBeanFactory在我们分析XmlBeanFactory就已经出现过了,他是XmlBeanFactory的爸爸

java 复制代码
protected DefaultListableBeanFactory createBeanFactory() {
    return new DefaultListableBeanFactory(getInternalParentBeanFactory());
}

我们接着往下看

java 复制代码
protected void customizeBeanFactory(DefaultListableBeanFactory beanFactory) {
    // 是否允许bean定义被覆盖
    if (this.allowBeanDefinitionOverriding != null) {
       beanFactory.setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
    }
    // 是否允许循环依赖
    if (this.allowCircularReferences != null) {
       beanFactory.setAllowCircularReferences(this.allowCircularReferences);
    }
}

customizeBeanFactory这个方法本质上就是为我们刚刚创建好的beanFactory设置allowBeanDefinitionOverriding和allowCircularReferences两个属性值,从属性名称我们可以猜测他们一个是判断是否允许bean定义被覆盖,另一个是判断是否允许循环依赖。说到循环依赖,有些小伙伴就迫不及待了,先别着急,插个眼,后面再说。

继续往下走,就到了loadBeanDefinitions方法了

java 复制代码
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
    // Create a new XmlBeanDefinitionReader for the given BeanFactory.
    // 初始化XmlBeanDefinitionReader
    XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);

    // Configure the bean definition reader with this context's
    // resource loading environment.
    // 为XmlBeanDefinitionReader设置上下文信息
    beanDefinitionReader.setEnvironment(this.getEnvironment());
    beanDefinitionReader.setResourceLoader(this);
    beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));

    // Allow a subclass to provide custom initialization of the reader,
    // then proceed with actually loading the bean definitions.
    // 空的方法,交给子类去实现(拓展点)
    initBeanDefinitionReader(beanDefinitionReader);
    // 将bean定义的加载委托给beanDefinitionReader处理
    loadBeanDefinitions(beanDefinitionReader);
}

这个方法首先创建了一个beanDefinitionReader,为他赋值了一些信息,并且提供了一个空的protected修饰的initBeanDefinitionReader,方便我们拓展,最后将bean定义的加载委托给beanDefinitionReader处理。

接下来我们继续看看loadBeanDefinitions方法

java 复制代码
protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException {
    Resource[] configResources = getConfigResources();
    if (configResources != null) {
       reader.loadBeanDefinitions(configResources);
    }
    String[] configLocations = getConfigLocations();
    if (configLocations != null) {
       reader.loadBeanDefinitions(configLocations);
    }
}

其中getConfigResources默认返回的是个空,如下所示

java 复制代码
@Nullable
protected Resource[] getConfigResources() {
    return null;
}

然后终于到XmlBeanDefinitionReader的loadBeanDefinitions方法了,点进去一看

java 复制代码
public int loadBeanDefinitions(String... locations) throws BeanDefinitionStoreException {
    Assert.notNull(locations, "Location array must not be null");
    int count = 0;
    for (String location : locations) {
        // 处理每一个xml路径的名称
       count += loadBeanDefinitions(location);
    }
    return count;
}

再跟进count += loadBeanDefinitions(location);这个方法,我们发现他实际上是调用的AbstractBeanDefinitionReader的loadBeanDefinitions方法

java 复制代码
public int loadBeanDefinitions(String location) throws BeanDefinitionStoreException {
    return loadBeanDefinitions(location, null);
}
java 复制代码
public int loadBeanDefinitions(String location, @Nullable Set<Resource> actualResources) throws BeanDefinitionStoreException {
    ResourceLoader resourceLoader = getResourceLoader();
    if (resourceLoader == null) {
       throw new BeanDefinitionStoreException(
             "Cannot load bean definitions from location [" + location + "]: no ResourceLoader available");
    }

    if (resourceLoader instanceof ResourcePatternResolver) {
       // Resource pattern matching available.
       try {
           // 这里就会根据传入的xml路劲,加载对应的资源了
          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;
    }
}

又调了一个重载的方法

java 复制代码
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的loadBeanDefinitions

java 复制代码
public int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException {
    return loadBeanDefinitions(new EncodedResource(resource));
}

而loadBeanDefinitions(new EncodedResource(resource))就是我们在《源码导读-Spring容器初始化流程-XmlBeanFactory》中重点分析过的流程了~

回到refreshBeanFactory()这个方法

java 复制代码
protected final void refreshBeanFactory() throws BeansException {
    // 判断bean是否存在
    // 我们第一次进来,bean肯定是不存在的
    if (hasBeanFactory()) {
       destroyBeans();
       closeBeanFactory();
    }
    try {
        // 创建bean工厂
       DefaultListableBeanFactory beanFactory = createBeanFactory();
        // 赋值序列化id
       beanFactory.setSerializationId(getId());
        // 自定义bean工厂
       customizeBeanFactory(beanFactory);
        // 载入bean定义
       loadBeanDefinitions(beanFactory);
        // 将创建好的bean工厂赋值给AbstractRefreshableApplicationContext的属性
       this.beanFactory = beanFactory;
    }
    catch (IOException ex) {
       throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
    }
}

第一次进来,我们初始化了一个beanFactory,并且放入了上下文中。如果不是第一次进来呢?那么根据代码必然会触发以下代码

java 复制代码
if (hasBeanFactory()) {
    // 销毁bean
   destroyBeans();
    // 关闭bean工厂
   closeBeanFactory();
}

然后再走下面我们刚刚分析过的流程,这样整个流程就像在刷新一样,所以这个方法叫refreshBeanFactory。

接着我们在回到obtainFreshBeanFactory方法,看看getBeanFactory方法

java 复制代码
public final ConfigurableListableBeanFactory getBeanFactory() {
    DefaultListableBeanFactory beanFactory = this.beanFactory;
    if (beanFactory == null) {
       throw new IllegalStateException("BeanFactory not initialized or already closed - " +
             "call 'refresh' before accessing beans via the ApplicationContext");
    }
    return beanFactory;
}

他的实现很简单,就是把属性beanFactory,取出来了。而属性beanFactory又是在refreshBeanFactory方法里面我们放进去的,完美~这条线我们也理解了

3、为使用bean工厂,做一些准备工作

java 复制代码
// Prepare the bean factory for use in this context.
// 为使用bean工厂,做一些准备工作
prepareBeanFactory(beanFactory);

跟进prepareBeanFactory方法,先瞄一眼,将注释翻译成中文如下

java 复制代码
protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
    // 告诉内部bean工厂使用上下文的类加载器等
    beanFactory.setBeanClassLoader(getClassLoader());
    beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
    beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));

    // 使用上下文回调配置bean工厂
    beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
    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接口作为可解析类型。
    // MessageSource已注册(并在自动装配中找到)作为bean。
    beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
    beanFactory.registerResolvableDependency(ResourceLoader.class, this);
    beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
    beanFactory.registerResolvableDependency(ApplicationContext.class, this);

    // 注册早期后处理器以检测内部bean作为ApplicationListeners。
    beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));

    // 检测LoadTimeWeaver并准备编织(如果找到)。
    if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
        beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
        // 设置临时ClassLoader用于类型匹配。
        beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
    }

    // 注册默认环境bean。
    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());
    }
}

首先我们可以看到beanFactory,被添加了一个类加载器,然后添加了一个类型为StandardBeanExpressionResolver的BeanExpressionResolver

而StandardBeanExpressionResolver是个什么东西呢?我们点进去看一下

java 复制代码
public StandardBeanExpressionResolver(@Nullable ClassLoader beanClassLoader) {
    this.expressionParser = new SpelExpressionParser(new SpelParserConfiguration(null, beanClassLoader));
}

出现了SPEL的表达式解析器!(SPEL 是 Spring Expression Language 的缩写,它是一种强大的表达式语言,支持在运行时查询和操作对象图。它类似于 Unified EL(统一表达式语言),但提供了额外的特性,使其更易于在 Spring 应用程序中使用。)

接着又添加了一个属性编辑器的注册器

java 复制代码
beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));

我们继续跟进代码,看看注册器是个什么东西

java 复制代码
public void registerCustomEditors(PropertyEditorRegistry registry) {
    ResourceEditor baseEditor = new ResourceEditor(this.resourceLoader, this.propertyResolver);
    doRegisterEditor(registry, Resource.class, baseEditor);
    doRegisterEditor(registry, ContextResource.class, baseEditor);
    doRegisterEditor(registry, InputStream.class, new InputStreamEditor(baseEditor));
    doRegisterEditor(registry, InputSource.class, new InputSourceEditor(baseEditor));
    doRegisterEditor(registry, File.class, new FileEditor(baseEditor));
    doRegisterEditor(registry, Path.class, new PathEditor(baseEditor));
    doRegisterEditor(registry, Reader.class, new ReaderEditor(baseEditor));
    doRegisterEditor(registry, URL.class, new URLEditor(baseEditor));

    ClassLoader classLoader = this.resourceLoader.getClassLoader();
    doRegisterEditor(registry, URI.class, new URIEditor(classLoader));
    doRegisterEditor(registry, Class.class, new ClassEditor(classLoader));
    doRegisterEditor(registry, Class[].class, new ClassArrayEditor(classLoader));

    if (this.resourceLoader instanceof ResourcePatternResolver) {
       doRegisterEditor(registry, Resource[].class,
             new ResourceArrayPropertyEditor((ResourcePatternResolver) this.resourceLoader, this.propertyResolver));
    }
}
java 复制代码
private void doRegisterEditor(PropertyEditorRegistry registry, Class<?> requiredType, PropertyEditor editor) {
    if (registry instanceof PropertyEditorRegistrySupport) {
       ((PropertyEditorRegistrySupport) registry).overrideDefaultEditor(requiredType, editor);
    }
    else {
       registry.registerCustomEditor(requiredType, editor);
    }
}

以上代码的作用,简单易懂,就是将这些编辑器放到了编辑器注册器中PropertyEditorRegistry,而这些编辑器有什么作用呢?随便点两个进去瞄一下,我们可以发现他是用来将String转化成相应对象的,比如InputStreamEditor是将String转化成InputStream,FileEditor是将String转化成File的。

添加了属性编辑注册器后,我们继续往下走

java 复制代码
beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
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添加了一个ApplicationContextAwareProcessor类型的对象,至于ApplicationContextAwareProcessor是什么我们后面再讲。

接着又调用ignoreDependencyInterface添加了一批需要忽略的aware接口,添加这个有什么用呢?我们已经在分析XmlBeanFactory的时候说到了,简而言之就是,如果一个bean实现了传入ignoreDependencylnterface方法的这些接口,Spring会忽略外界注入的任何依赖到该bean中,只允许Spring容器内部调用接口的方法来注入相应的依赖。

接着分析以下代码

java 复制代码
// 在普通工厂中未注册BeanFactory接口作为可解析类型。
// MessageSource已注册(并在自动装配中找到)作为bean。
beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
beanFactory.registerResolvableDependency(ResourceLoader.class, this);
beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
beanFactory.registerResolvableDependency(ApplicationContext.class, this);

跟进beanFactory调用的registerResolvableDependency接口

java 复制代码
public void registerResolvableDependency(Class<?> dependencyType, @Nullable Object autowiredValue) {
    Assert.notNull(dependencyType, "Dependency type must not be null");
    if (autowiredValue != null) {
       if (!(autowiredValue instanceof ObjectFactory || dependencyType.isInstance(autowiredValue))) {
          throw new IllegalArgumentException("Value [" + autowiredValue +
                "] does not implement specified dependency type [" + dependencyType.getName() + "]");
       }
       this.resolvableDependencies.put(dependencyType, autowiredValue);
    }
}

我们可以发现其实就是为接口指定了对应的依赖,他们以<key,value>的方式放在了一个Map中

java 复制代码
private final Map<Class<?>, Object> resolvableDependencies = new ConcurrentHashMap<>(16);

至于这个Map有什么用,这里看不出来,如果实在感兴趣我们可以通过这个使用这个Map的地方来推导一下。

我们以beanFactory.registerResolvableDependency(ApplicationContext.class, this)这行代码举例,他的作用是告诉Spring框架,当前对象(this)可以作为ApplicationContext接口的实现类进行自动装配。这样在Spring的依赖注入过程中,如果需要注入ApplicationContext类型的对象,就会使用当前对象(this)作为实现类进行注入。也就是说,即便你亲自编写了一个实现该接口的类并将其注入到Spring容器中,Spring最终仍会对你所写的那个bean视而不见,而采用registerResolvableDependency方法中设置的beanFactory来提供相应的依赖。

接着往下看,什么后置处理器、监听、编织、单例啥的都出来了,这一块感觉有点啃不动,我们插个眼,后面再来看。

java 复制代码
// 注册早期后处理器以检测内部bean作为ApplicationListeners。
beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));

// 检测LoadTimeWeaver并准备编织(如果找到)。
if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
    beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
    // 设置临时ClassLoader用于类型匹配。
    beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
}

// 注册默认环境bean。
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());
}

4、允许在上下文子类中对bean工厂进行后处理

java 复制代码
// Allows post-processing of the bean factory in context subclasses.
// 允许在上下文子类中对bean工厂进行后处理。
postProcessBeanFactory(beanFactory);

这是一个protected修饰的空方法,很明显也是Spring给我们的拓展点。Spring为什么要提供这一个拓展点呢?

vbnet 复制代码
Modify the application context's internal bean factory after its standard initialization. All bean definitions will have been loaded, but no beans will have been instantiated yet. This allows for registering special BeanPostProcessors etc in certain ApplicationContext implementations.

我们可以从方法的注释中知道,Spring通过postProcessBeanFactory方法给了我们一次机会,在bean实例化之前,可以修改bean的一些属性信息。

5、调用bean工厂的后置处理器

java 复制代码
// Invoke factory processors registered as beans in the context.
// 调用bean工厂的后置处理器
invokeBeanFactoryPostProcessors(beanFactory);

跟进invokeBeanFactoryPostProcessors方法

java 复制代码
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()));
    }
}

再跟进PostProcessorRegistrationDelegate的invokeBeanFactoryPostProcessors方法

java 复制代码
public static void invokeBeanFactoryPostProcessors(
       ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {

    // Invoke BeanDefinitionRegistryPostProcessors first, if any.
    Set<String> processedBeans = new HashSet<>();

    if (beanFactory instanceof BeanDefinitionRegistry) {
       BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
       List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>();
       List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>();

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

       // Do not initialize FactoryBeans here: We need to leave all regular beans
       // uninitialized to let the bean factory post-processors apply to them!
       // Separate between BeanDefinitionRegistryPostProcessors that implement
       // PriorityOrdered, Ordered, and the rest.
       List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();

       // First, invoke the BeanDefinitionRegistryPostProcessors that implement PriorityOrdered.
       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);
       currentRegistryProcessors.clear();

       // Next, invoke the BeanDefinitionRegistryPostProcessors that implement Ordered.
       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();

       // Finally, invoke all other BeanDefinitionRegistryPostProcessors until no further ones appear.
       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();
       }

       // Now, invoke the postProcessBeanFactory callback of all processors handled so far.
       invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
       invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
    }

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

    // Do not initialize FactoryBeans here: We need to leave all regular beans
    // uninitialized to let the bean factory post-processors apply to them!
    String[] postProcessorNames =
          beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);

    // Separate between BeanFactoryPostProcessors that implement PriorityOrdered,
    // Ordered, and the rest.
    List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
    List<String> orderedPostProcessorNames = new ArrayList<>();
    List<String> nonOrderedPostProcessorNames = new ArrayList<>();
    for (String ppName : postProcessorNames) {
       if (processedBeans.contains(ppName)) {
          // skip - already processed in first phase above
       }
       else if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
          priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));
       }
       else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
          orderedPostProcessorNames.add(ppName);
       }
       else {
          nonOrderedPostProcessorNames.add(ppName);
       }
    }

    // First, invoke the BeanFactoryPostProcessors that implement PriorityOrdered.
    sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
    invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);

    // Next, invoke the BeanFactoryPostProcessors that implement Ordered.
    List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size());
    for (String postProcessorName : orderedPostProcessorNames) {
       orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
    }
    sortPostProcessors(orderedPostProcessors, beanFactory);
    invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);

    // Finally, invoke all other BeanFactoryPostProcessors.
    List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size());
    for (String postProcessorName : nonOrderedPostProcessorNames) {
       nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
    }
    invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);

    // Clear cached merged bean definitions since the post-processors might have
    // modified the original metadata, e.g. replacing placeholders in values...
    beanFactory.clearMetadataCache();
}

粗瞄一眼以上代码,脑海中直接浮现出了可爱的羊驼~

但是谁让我们是在阅读Spring源码呢,而且这一坨看起来也不是可以随便就跳过的地方~那么,干就完了!

首先我们来啃第一个if,我们在分析obtainFreshBeanFactory方法的时候,知道了这个beanFactory其实就是DefaultListableBeanFactory,而DefaultListableBeanFactory实现了BeanDefinitionRegistry接口,所以第一个if是true满足条件的。

java 复制代码
public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory
       implements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable

接着分析以下代码

java 复制代码
BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
// 存放BeanFactoryPostProcessor的集合
List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>();
// 存放BeanDefinitionRegistryPostProcessor的集合
// BeanDefinitionRegistryPostProcessor是个什么东西呢?他是BeanFactoryPostProcessor的子类
List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>();

// 遍历我们传进来的BeanFactoryPostProcessor
for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
    // 1 如果他的类型是BeanDefinitionRegistryPostProcessor
    if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
       BeanDefinitionRegistryPostProcessor registryProcessor =
             (BeanDefinitionRegistryPostProcessor) postProcessor;
        // 1.1 那么执行postProcessBeanDefinitionRegistry方法,将要注册的BeanDefinition先注册到Spring容器中
       registryProcessor.postProcessBeanDefinitionRegistry(registry);
        // 1.2 添加到BeanDefinitionRegistryPostProcessor的集合中
       registryProcessors.add(registryProcessor);
    }
    // 2 如果类型不是BeanDefinitionRegistryPostProcessor
    else {
        // 2.1 添加到BeanFactoryPostProcessor的集合中
       regularPostProcessors.add(postProcessor);
    }
}

上面代码看着很多,其实分析起来也不复杂。无非就是以下几步:

1、初始化完两个集合

2、遍历参数beanFactoryPostProcessors

3、将BeanDefinitionRegistryPostProcessor和BeanFactoryPostProcessor分别存放到相应的集合中

4、在将接口BeanDefinitionRegistryPostProcessor的实现类存放到集合之前,会预先执行接口中的方法postProcessBeanDefinitionRegistry,将要注册的BeanDefinition先注册到Spring容器中

我们继续往下分析,先为代码添加注释

java 复制代码
// 这是个临时集合,用于保存当前需要执行的BeanDefinitionRegistryPostProcessor
List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();

// 从beanFactory中获取所有实现了BeanDefinitionRegistryPostProcessor的bean
String[] postProcessorNames =
       beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
// 遍历这些bean
for (String ppName : postProcessorNames) {
    // 如果他们又实现了PriorityOrdered
    if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
        // 放入BeanDefinitionRegistryPostProcessor临时集合中
       currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
        // 放入set集合中,避免被重复执行
       processedBeans.add(ppName);
    }
}
// 对集合currentRegistryProcessors进行排序
sortPostProcessors(currentRegistryProcessors, beanFactory);
// 添加到registryProcessors的集合中
registryProcessors.addAll(currentRegistryProcessors);
// 执行currentRegistryProcessors中所有bean的postProcessBeanDefinitionRegistry方法
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
// 清空临时集合currentRegistryProcessors
currentRegistryProcessors.clear();

跟进sortPostProcessors方法,看看Spring是如何排序的

java 复制代码
private static void sortPostProcessors(List<?> postProcessors, ConfigurableListableBeanFactory beanFactory) {
    // Nothing to sort?
    if (postProcessors.size() <= 1) {
       return;
    }
    Comparator<Object> comparatorToUse = null;
    if (beanFactory instanceof DefaultListableBeanFactory) {
       comparatorToUse = ((DefaultListableBeanFactory) beanFactory).getDependencyComparator();
    }
    if (comparatorToUse == null) {
       comparatorToUse = OrderComparator.INSTANCE;
    }
    postProcessors.sort(comparatorToUse);
}

sortPostProcessors的postProcessors都是实现了PriorityOrdered接口的,而PriorityOrdered又继承至Ordered,所以会根据getOrder方法的返回值进行排序,值越小优先级越大。

跟进invokeBeanDefinitionRegistryPostProcessors

java 复制代码
private static void invokeBeanDefinitionRegistryPostProcessors(
       Collection<? extends BeanDefinitionRegistryPostProcessor> postProcessors, BeanDefinitionRegistry registry) {

    for (BeanDefinitionRegistryPostProcessor postProcessor : postProcessors) {
       postProcessor.postProcessBeanDefinitionRegistry(registry);
    }
}

他其实是执行了currentRegistryProcessors中所有bean的postProcessBeanDefinitionRegistry方法。

接着分析下一块代码

java 复制代码
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();

很明显,这里只不过处理的是既实现了BeanDefinitionRegistryPostProcessor又实现了Order接口的bean,处理方式都和上一块代码一样

继续看下面的代码

java 复制代码
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();
}

也是一样的,只是处理的是PriorityOrdered和Ordered都没有实现的BeanDefinitionRegistryPostProcessor

最后看看这个if中最后两行代码

java 复制代码
invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
java 复制代码
private static void invokeBeanFactoryPostProcessors(
       Collection<? extends BeanFactoryPostProcessor> postProcessors, ConfigurableListableBeanFactory beanFactory) {

    for (BeanFactoryPostProcessor postProcessor : postProcessors) {
       postProcessor.postProcessBeanFactory(beanFactory);
    }
}

其实都是统一调用方法postProcessBeanFactory来修改BeanDefinition。

对实现了BeanDefinitionRegistryPostProcessor的类的处理,我们分析完了,接下来看看后面的代码。

java 复制代码
String[] postProcessorNames =
       beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);

// Separate between BeanFactoryPostProcessors that implement PriorityOrdered,
// Ordered, and the rest.
List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
List<String> orderedPostProcessorNames = new ArrayList<>();
List<String> nonOrderedPostProcessorNames = new ArrayList<>();
for (String ppName : postProcessorNames) {
    if (processedBeans.contains(ppName)) {
       // skip - already processed in first phase above
    }
    else if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
       priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));
    }
    else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
       orderedPostProcessorNames.add(ppName);
    }
    else {
       nonOrderedPostProcessorNames.add(ppName);
    }
}

熟悉的逻辑,这里对实现了PriorityOrdered的BeanFactoryPostProcessor,实现了Ordered的BeanFactoryPostProcessor,以及两个接口都没有实现的BeanFactoryPostProcessor,做了分组存储。

我们可以大胆猜测后面多半是对他们进行排序以及调用postProcessBeanFactory方法了

java 复制代码
// First, invoke the BeanFactoryPostProcessors that implement PriorityOrdered.
sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);

// Next, invoke the BeanFactoryPostProcessors that implement Ordered.
List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size());
for (String postProcessorName : orderedPostProcessorNames) {
    orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
}
sortPostProcessors(orderedPostProcessors, beanFactory);
invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);

// Finally, invoke all other BeanFactoryPostProcessors.
List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size());
for (String postProcessorName : nonOrderedPostProcessorNames) {
    nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
}
invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);

// Clear cached merged bean definitions since the post-processors might have
// modified the original metadata, e.g. replacing placeholders in values...
beanFactory.clearMetadataCache();

果不其然,Spring后面的确是这么做的,并且还在最后清理了beanFactory的元数据缓存。

6、注册Bean的后置处理器

回到refresh方法后,接下来该看看registerBeanPostProcessors方法了

java 复制代码
// Register bean processors that intercept bean creation.
registerBeanPostProcessors(beanFactory);

跟进registerBeanPostProcessors方法

java 复制代码
protected void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory) {
    PostProcessorRegistrationDelegate.registerBeanPostProcessors(beanFactory, this);
}

可以发现他其实是委托给了PostProcessorRegistrationDelegate调用registerBeanPostProcessors方法

跟进registerBeanPostProcessors方法

java 复制代码
public static void registerBeanPostProcessors(
       ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {
	// 1、获取所有实现了BeanPostProcessor的bean名称
    String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);

    // Register BeanPostProcessorChecker that logs an info message when
    // a bean is created during BeanPostProcessor instantiation, i.e. when
    // a bean is not eligible for getting processed by all BeanPostProcessors.
    // 2、往beanFactory的后置处理器中放了一个BeanPostProcessorChecker,一看就是一个校验器,对主流程的影响并不大
    int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length;
    beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));

    // Separate between BeanPostProcessors that implement PriorityOrdered,
    // Ordered, and the rest.
    // 3、熟悉的代码,又是对实现接口的类先分组
    List<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
    List<BeanPostProcessor> internalPostProcessors = new ArrayList<>();
    List<String> orderedPostProcessorNames = new ArrayList<>();
    List<String> nonOrderedPostProcessorNames = new ArrayList<>();
    for (String ppName : postProcessorNames) {
       if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
          BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
          priorityOrderedPostProcessors.add(pp);
          if (pp instanceof MergedBeanDefinitionPostProcessor) {
             internalPostProcessors.add(pp);
          }
       }
       else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
          orderedPostProcessorNames.add(ppName);
       }
       else {
          nonOrderedPostProcessorNames.add(ppName);
       }
    }

    // First, register the BeanPostProcessors that implement PriorityOrdered.
    // 4、排序,老朋友了
    sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
    // 5、注册BeanPostProcessor,前面调用bean工厂的后置处理器-invokeBeanFactoryPostProcessors时,是直接执行的方法
    // 这里看来是放进去,没有直接执行
    registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);

    // Next, register the BeanPostProcessors that implement Ordered.
    // 6、模版的处理方式
    List<BeanPostProcessor> orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size());
    for (String ppName : orderedPostProcessorNames) {
       BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
       orderedPostProcessors.add(pp);
       if (pp instanceof MergedBeanDefinitionPostProcessor) {
          internalPostProcessors.add(pp);
       }
    }
    sortPostProcessors(orderedPostProcessors, beanFactory);
    registerBeanPostProcessors(beanFactory, orderedPostProcessors);

    // Now, register all regular BeanPostProcessors.
    // 7、模版的处理方式
    List<BeanPostProcessor> nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size());
    for (String ppName : nonOrderedPostProcessorNames) {
       BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
       nonOrderedPostProcessors.add(pp);
       if (pp instanceof MergedBeanDefinitionPostProcessor) {
          internalPostProcessors.add(pp);
       }
    }
    registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors);

    // Finally, re-register all internal BeanPostProcessors.
    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).
    beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext));
}

虽然代码看起来很多,但是其实稍微瞟一眼,我们就能发现很多老熟人。总的说来,就和前面调用bean工厂的后置处理器-invokeBeanFactoryPostProcessors时是差不多的。

首先,从beanFactory中获取所有实现了BeanPostProcessor的bean名称。然后,对实现了PriorityOrdered接口、实现了Ordered接口以及两个接口都没实现的BeanPostProcessor,判断是否存在同时实现接口MergedBeanDefinitionPostProcessor的类,将其添加到集合internalPostProcessors中,接着进行排序,并且注册到beanFactory中。

7、初始化消息源

java 复制代码
// Initialize message source for this context.
initMessageSource();

跟进initMessageSource方法

java 复制代码
protected void initMessageSource() {
    ConfigurableListableBeanFactory beanFactory = getBeanFactory();
    if (beanFactory.containsLocalBean(MESSAGE_SOURCE_BEAN_NAME)) {
       this.messageSource = beanFactory.getBean(MESSAGE_SOURCE_BEAN_NAME, MessageSource.class);
       // Make MessageSource aware of parent MessageSource.
       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());
          }
       }
       if (logger.isTraceEnabled()) {
          logger.trace("Using MessageSource [" + this.messageSource + "]");
       }
    }
    else {
       // Use empty MessageSource to be able to accept getMessage calls.
       DelegatingMessageSource dms = new DelegatingMessageSource();
       dms.setParentMessageSource(getInternalParentMessageSource());
       this.messageSource = dms;
       beanFactory.registerSingleton(MESSAGE_SOURCE_BEAN_NAME, this.messageSource);
       if (logger.isTraceEnabled()) {
          logger.trace("No '" + MESSAGE_SOURCE_BEAN_NAME + "' bean, using [" + this.messageSource + "]");
       }
    }
}

看了一下代码其实就是初始化了一个消息源放到了Spring中,要么放MessageSource,要么放DelegatingMessageSource,看样子对我们主流程影响不大。查阅相关资料,可以发现MessageSource其实是用来处理国际化的。所以这层分析到此为止。

8、初始化广播器

java 复制代码
// Initialize event multicaster for this context.
initApplicationEventMulticaster();

跟进initApplicationEventMulticaster方法

java 复制代码
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);
       if (logger.isTraceEnabled()) {
          logger.trace("Using ApplicationEventMulticaster [" + this.applicationEventMulticaster + "]");
       }
    }
    else {
       this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
       beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster);
       if (logger.isTraceEnabled()) {
          logger.trace("No '" + APPLICATION_EVENT_MULTICASTER_BEAN_NAME + "' bean, using " +
                "[" + this.applicationEventMulticaster.getClass().getSimpleName() + "]");
       }
    }
}

可以看到逻辑和初始化消息源是差不多的,主要看beanFactory中是否存在名称为APPLICATION_EVENT_MULTICASTER_BEAN_NAME(applicationEventMulticaster)的bean。如果存在的话,则直接从容器中获取并赋值给applicationEventMulticaster,否则直接创建一个SimpleApplicationEventMulticaster类型的对象并设置到Spring容器beanFactory中。

9、留给子类拓展的onRefresh方法

java 复制代码
// Initialize other special beans in specific context subclasses.
onRefresh();

跟进onRefresh

java 复制代码
protected void onRefresh() throws BeansException {
    // For subclasses: do nothing by default.
}

我们发现,他是一个protected修饰的空方法,也就是说他也是Spring留给子类的一个扩展方法。

10、初始化监听器

在第8点,我们聊到了初始化广播器,接下来我们看看初始化监听器

java 复制代码
// Check for listener beans and register them.
registerListeners();

点进registerListeners方法

java 复制代码
protected void registerListeners() {
    // Register statically specified listeners first.
    // 通过getApplicationListeners方法,获取上下文中的监听器,并将监听器添加到广播器中
    for (ApplicationListener<?> listener : getApplicationListeners()) {
       getApplicationEventMulticaster().addApplicationListener(listener);
    }

    // Do not initialize FactoryBeans here: We need to leave all regular beans
    // uninitialized to let post-processors apply to them!
    // 获取类型为ApplicationListener的bean名称,并将监听器添加到广播器中
    String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
    for (String listenerBeanName : listenerBeanNames) {
       getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
    }

    // Publish early application events now that we finally have a multicaster...
    // 发布应用早期事件
    Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;
    this.earlyApplicationEvents = null;
    if (!CollectionUtils.isEmpty(earlyEventsToProcess)) {
       for (ApplicationEvent earlyEvent : earlyEventsToProcess) {
          getApplicationEventMulticaster().multicastEvent(earlyEvent);
       }
    }
}

11、预先实例化非延迟加载的单例bean

java 复制代码
// Instantiate all remaining (non-lazy-init) singletons.
finishBeanFactoryInitialization(beanFactory);

跟进finishBeanFactoryInitialization方法

java 复制代码
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
    // 初始化此上下文的转换服务。
    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));
    }

    // 如果没有注册任何BeanFactoryPostProcessor(如PropertySourcesPlaceholderConfigurer bean),则注册默认的嵌入式值解析器:
    // 在这一点上,主要是为了解析注解属性值。
    if (!beanFactory.hasEmbeddedValueResolver()) {
       beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal));
    }

    // 尽早初始化LoadTimeWeaverAware beans,以便尽早注册它们的转换器。
    String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
    for (String weaverAwareName : weaverAwareNames) {
       getBean(weaverAwareName);
    }

    // 停止使用临时ClassLoader进行类型匹配。
    beanFactory.setTempClassLoader(null);

    // 允许缓存所有bean定义元数据,不期望进一步更改。
    beanFactory.freezeConfiguration();

    // 实例化所有剩余的(非延迟初始化)单例。
    beanFactory.preInstantiateSingletons();
}

我们发现这个方法其实是在为beanFactory添加一些属性,我们看一下他是如何实例化所有剩余的(非延迟初始化)单例bean的

java 复制代码
public void preInstantiateSingletons() throws BeansException {
    if (logger.isTraceEnabled()) {
       logger.trace("Pre-instantiating singletons in " + this);
    }

    // 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<String> beanNames = new ArrayList<>(this.beanDefinitionNames);

    // Trigger initialization of all non-lazy singleton beans...
    for (String beanName : beanNames) {
       RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
       if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
          if (isFactoryBean(beanName)) {
             Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
             if (bean instanceof FactoryBean) {
                FactoryBean<?> factory = (FactoryBean<?>) bean;
                boolean isEagerInit;
                if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
                   isEagerInit = AccessController.doPrivileged(
                         (PrivilegedAction<Boolean>) ((SmartFactoryBean<?>) factory)::isEagerInit,
                         getAccessControlContext());
                }
                else {
                   isEagerInit = (factory instanceof SmartFactoryBean &&
                         ((SmartFactoryBean<?>) factory).isEagerInit());
                }
                if (isEagerInit) {
                   getBean(beanName);
                }
             }
          }
          else {
             getBean(beanName);
          }
       }
    }

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

首先,Spring会逐一检查容器中注册的所有BeanDefinition。如果某个BeanDefinition的属性scope的值为singleton,并且属性lazyInit的值为false,那么我们会调用getBean方法去实例化这个bean。

12、最后一步:发布相应事件

最后一个finishRefresh方法了

java 复制代码
// Last step: publish corresponding event.
finishRefresh();

我们点进去看看

java 复制代码
protected void finishRefresh() {
    // Clear context-level resource caches (such as ASM metadata from scanning).
    // 1、清空源缓存
    clearResourceCaches();

    // Initialize lifecycle processor for this context.
    // 2、初始化生命周期处理器
    initLifecycleProcessor();

    // Propagate refresh to lifecycle processor first.
    // 3、开启生命周期
    getLifecycleProcessor().onRefresh();

    // Publish the final event.
    // 4、发布上下文中已经完成刷新的事件
    publishEvent(new ContextRefreshedEvent(this));

    // Participate in LiveBeansView MBean, if active.
    // 5、将Spring容器注册到LiveBeansView中
    LiveBeansView.registerApplicationContext(this);
}

第一个方法clearResourceCaches()很简单,就是将resourceCaches置为了空

第二个方法initLifecycleProcessor,我们跟跟进去看看

java 复制代码
protected void initLifecycleProcessor() {
    ConfigurableListableBeanFactory beanFactory = getBeanFactory();
    if (beanFactory.containsLocalBean(LIFECYCLE_PROCESSOR_BEAN_NAME)) {
       this.lifecycleProcessor =
             beanFactory.getBean(LIFECYCLE_PROCESSOR_BEAN_NAME, LifecycleProcessor.class);
       if (logger.isTraceEnabled()) {
          logger.trace("Using LifecycleProcessor [" + this.lifecycleProcessor + "]");
       }
    }
    else {
       DefaultLifecycleProcessor defaultProcessor = new DefaultLifecycleProcessor();
       defaultProcessor.setBeanFactory(beanFactory);
       this.lifecycleProcessor = defaultProcessor;
       beanFactory.registerSingleton(LIFECYCLE_PROCESSOR_BEAN_NAME, this.lifecycleProcessor);
       if (logger.isTraceEnabled()) {
          logger.trace("No '" + LIFECYCLE_PROCESSOR_BEAN_NAME + "' bean, using " +
                "[" + this.lifecycleProcessor.getClass().getSimpleName() + "]");
       }
    }
}

可以看到又是似曾相识的代码,在方法initLifecycleProcessor中,首先会检查Spring容器中是否存在名称为lifecycleProcessor的bean。如果存在,则直接从Spring容器中获取该bean并赋值给成员变量lifecycleProcessor;如果不存在,则会创建一个DefaultLifecycleProcessor类型的对象,并将其赋值给成员变量lifecycleProcessor,最后再将该对象注入到Spring容器中。

而创建这个对象有什么用呢?我们在下一个方法就能找到答案

java 复制代码
// Propagate refresh to lifecycle processor first.
getLifecycleProcessor().onRefresh();

跟进onRefresh方法

java 复制代码
public void onRefresh() {
    startBeans(true);
    this.running = true;
}

目测调用startBeans开启了生命周期,并且将运行状态设为了true

跟进startBeans方法

java 复制代码
private void startBeans(boolean autoStartupOnly) {
    Map<String, Lifecycle> lifecycleBeans = getLifecycleBeans();
    Map<Integer, LifecycleGroup> phases = new HashMap<>();
    lifecycleBeans.forEach((beanName, bean) -> {
       if (!autoStartupOnly || (bean instanceof SmartLifecycle && ((SmartLifecycle) bean).isAutoStartup())) {
          int phase = getPhase(bean);
          LifecycleGroup group = phases.get(phase);
          if (group == null) {
             group = new LifecycleGroup(phase, this.timeoutPerShutdownPhase, lifecycleBeans, autoStartupOnly);
             phases.put(phase, group);
          }
          group.add(beanName, bean);
       }
    });
    if (!phases.isEmpty()) {
       List<Integer> keys = new ArrayList<>(phases.keySet());
       Collections.sort(keys);
       for (Integer key : keys) {
          phases.get(key).start();
       }
    }
}

我们可以看到他会从Spring容器中获取所有实现了Lifecycle接口的bean,然后调用start方法来开启它们的生命周期,主要是以下这行代码

java 复制代码
phases.get(key).start();

然后我们回到finishRefresh方法,剩下两步也比较简单

kotlin 复制代码
// 4、发布上下文中已经完成刷新的事件
publishEvent(new ContextRefreshedEvent(this));

// Participate in LiveBeansView MBean, if active.
// 5、将Spring容器注册到LiveBeansView中
LiveBeansView.registerApplicationContext(this);

就是发布事件和注册到生命周期视图中。

Spring容器初始化流程图-ApplicationContext

至此refresh()方法就分析完了,ApplicationContext中Spring容器的初始化流程也结束了,最后我们通过一张流程图来结束我们这一章的学习。

相关推荐
2401_857622666 小时前
SpringBoot框架下校园资料库的构建与优化
spring boot·后端·php
2402_857589366 小时前
“衣依”服装销售平台:Spring Boot框架的设计与实现
java·spring boot·后端
哎呦没7 小时前
大学生就业招聘:Spring Boot系统的架构分析
java·spring boot·后端
_.Switch7 小时前
Python Web 应用中的 API 网关集成与优化
开发语言·前端·后端·python·架构·log4j
编程、小哥哥7 小时前
netty之Netty与SpringBoot整合
java·spring boot·spring
杨哥带你写代码9 小时前
足球青训俱乐部管理:Spring Boot技术驱动
java·spring boot·后端
AskHarries9 小时前
读《show your work》的一点感悟
后端
A尘埃9 小时前
SpringBoot的数据访问
java·spring boot·后端
yang-23079 小时前
端口冲突的解决方案以及SpringBoot自动检测可用端口demo
java·spring boot·后端
Marst Code9 小时前
(Django)初步使用
后端·python·django