解密Spring ApplicationContext:源码剖析与内部刷新 refresh 机制

ApplicationContext 概述

ApplicationContext 的定义和作用

ApplicationContext 是 Spring 框架中的一个核心接口,它是 Spring IoC 容器的一个高级形式,用于提供应用程序级别的配置和管理功能。ApplicationContext 接口的定义和作用如下:

定义:

ApplicationContext 接口是 Spring 框架中用于表示 IoC 容器的接口,它继承了 BeanFactory 接口,并扩展了一些应用级别的功能和特性。

作用:

  • **管理 Bean:**ApplicationContext 负责管理应用程序中的 Bean 对象,包括实例化、配置和组装 Bean,并负责管理 Bean 的生命周期。
  • **提供依赖注入:**ApplicationContext 支持依赖注入(Dependency Injection),它能够自动解析和注入 Bean 之间的依赖关系,实现松耦合的组件之间的协作。
  • **支持国际化:**ApplicationContext 提供了国际化(i18n)的支持,可以方便地实现多语言的应用程序。
  • **事件发布和监听:**ApplicationContext 支持事件(Event)的发布和监听,可以让应用程序组件之间进行事件通信,实现解耦合的事件驱动模型。
  • **资源加载:**ApplicationContext 能够加载和管理应用程序中的各种资源,包括文本、图像、视频等。
  • AOP 支持: ApplicationContext 支持面向切面编程(AOP),可以方便地实现横切关注点的管理。
  • **事务管理:**ApplicationContext 支持声明式事务管理,可以方便地配置和管理应用程序中的事务。
  • **提供各种扩展点:**ApplicationContext 提供了各种扩展点,可以通过自定义 BeanPostProcessor、BeanFactoryPostProcessor 等来对容器进行定制和扩展。

ApplicationContext 与 BeanFactory 的区别与联系

区别:

  • **初始化时机:**ApplicationContext 在容器初始化时会预先实例化和配置所有的 Bean,而 BeanFactory 则是在请求获取 Bean 时才进行实例化和配置,延迟初始化,因此 ApplicationContext 的启动速度相对较慢。
  • **功能特性:**ApplicationContext 在 BeanFactory 的基础上提供了更多的功能和特性,如国际化支持、事件发布和监听、AOP、事务管理等,因此 ApplicationContext 是一个更加高级的 IoC 容器。
  • **资源加载:**ApplicationContext 可以加载多种类型的资源,如文件、URL、类路径等,而 BeanFactory 只能加载类路径下的资源。
  • **容器扩展:**ApplicationContext 提供了各种扩展点,如 BeanPostProcessor、BeanFactoryPostProcessor 等,可以对容器进行定制和扩展,而 BeanFactory 的扩展点相对较少。

联系:

  • **继承关系:**ApplicationContext 接口继承了 BeanFactory 接口,因此 ApplicationContext 具有 BeanFactory 的所有功能,并在此基础上进行了扩展和增强。
  • **共同目的:**ApplicationContext 和 BeanFactory 都是 Spring 框架中用于管理 Bean 的核心接口,它们的共同目的都是实现 IoC(控制反转)和 DI(依赖注入),实现松耦合的组件之间的协作。

ApplicationContext 的继承结构

Spring Framework 中定义的顶级接口,它代表了 Spring 容器,负责加载应用程序的 bean 定义、将 bean 实例化、配置 bean 依赖关系等。

ApplicationContext 接口有多个实现,包括:

  • AnnotationConfigApplicationContext:基于注解的配置类创建应用上下文,通过传递配置类的类对象,可以将其用作应用上下文的配置来源。

  • ClassPathXmlApplicationContext:基于 XML 配置文件创建应用上下文,通过传递 XML 配置文件的路径,可以创建一个应用上下文来加载和管理 bean。

  • FileSystemXmlApplicationContext:从文件系统中加载 XML 配置文件创建应用上下文。

  • WebApplicationContext:专门用于在 Web 应用程序中使用的应用上下文。

AnnotationConfigApplicationContext

正式开始研究 AnnotationConfigApplicationContext 之前先分享一个小技巧,基于已学的知识内容,我们知道:

  1. 所有注册的 Bean 都会存储在 BeanFactory 内部的 beanDefinitionMap 这个成员变量中
  2. 所有创建的单例的 Bean 都会存储在 BeanFactory 内部的 singletonObjects 这个成员变量中

所以我们 Debug 的时候可以时刻观察这两个变量中的数据变化。

AnnotationConfigApplicationContext 是 Spring 框架中的一个 ApplicationContext 接口的实现,它用于基于注解的配置来加载和管理 Bean。相比于传统的 XML 配置方式,使用 AnnotationConfigApplicationContext 可以更加方便地实现配置的管理,减少了配置文件的数量和复杂度,提高了开发效率。

下面是 AnnotationConfigApplicationContext 的主要特点和用法:

  1. 基于注解的配置: AnnotationConfigApplicationContext 主要用于基于注解的配置,它可以扫描指定的包路径,自动注册带有特定注解的 Bean 定义,如 @Component、@Service、@Repository、@Controller 等。
  2. 纯 Java 配置: 使用 AnnotationConfigApplicationContext 可以完全摆脱 XML 配置文件,采用纯 Java 的方式来配置 Spring 应用程序,通过 JavaConfig 类来定义 Bean。
  3. 灵活性和可读性: AnnotationConfigApplicationContext 提供了一种更加灵活和可读性更高的配置方式,可以通过 Java 代码来组织和管理 Bean,避免了繁琐的 XML 配置。
  4. 支持条件化配置: AnnotationConfigApplicationContext 支持条件化配置,可以根据条件来动态地选择是否注册某个 Bean 定义,实现更加灵活的配置管理。

AnnotationConfigApplicationContext 的使用

AnnotationConfigApplicationContext 的使用可以分为两种,第一种传入配置 Bean(支持多个),第二种传入要扫描的包路径(支持多个)。示例代码如下:

AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext("world.xuewei");

这两种方式首先都要进行 BeanDefinition 的创建和注册,分别由 AnnotatedBeanDefinitionReader 和 ClassPathBeanDefinitionScanner 处理,处理细节可翻阅前面的文章:《深入解析Spring BeanDefinition:理解加载、解析与注册的全过程》。

AnnotationConfigApplicationContext 的构造

基于上面的两种用法,AnnotationConfigApplicationContext 提供了两种构造,代码如下:

private final AnnotatedBeanDefinitionReader reader;

private final ClassPathBeanDefinitionScanner scanner;

public AnnotationConfigApplicationContext() {
    // 无参构造,用于初始化两个解析工具
    this.reader = new AnnotatedBeanDefinitionReader(this);
    this.scanner = new ClassPathBeanDefinitionScanner(this);
}

/**
 * 传入配置 Bean 方式
 */
public AnnotationConfigApplicationContext(Class<?>... annotatedClasses) {
    this();
    register(annotatedClasses);
    refresh();
}

/**
 * 传入扫描包的方式
 */
public AnnotationConfigApplicationContext(String... basePackages) {
    this();
    scan(basePackages);
    refresh();
}

观察一下这两种构造的大概结构,首先都是调用了无参构造去初始化这两个解析工具,其次分别调用各自情况的解析工具去执行 BeanDefinition 的解析、创建和注册。最后都调用了 refresh 这个方法。

通过断点,我们可以发现构造的时候在执行无参构造的步骤之后,beanDefinitionMap 中已经有 5 个数据,而 singletonObjects 中还是 0:

这五个都是 Spring 在最开始就为我们自动注册的 Bean,其中还有两个有关 Spring 事件相关的我们先忽略,剩下的还有三个重要的类型:

  1. ConfigurationClassPostProcessor:处理 @Configuration、@ComponentScan、@Import、@ImportResource、@PropertySource 注解。
  2. AutowiredAnnotationBeanPostProcessor:处理 @Autowired、@Value、@Inject 注解。
  3. CommonAnnotationBeanPostProcessor:处理 JSR-250 规范中的注解,比如 @Resource、@PostConstruct、@PreDestory 等。

这三个 Bean 中,ConfigurationClassPostProcessor 是 BeanFactoryPostProcessor 的实现类,而 AutowiredAnnotationBeanPostProcessor 和 CommonAnnotationBeanPostProcessor 都是 BeanPostProcessor 的实现类。

那么再深入一下源码,找到真正注册这五个 Bean 的地方:

AnnotationConfigApplicationContext 的无参构造会初始化 AnnotatedBeanDefinitionReader 对象,而注册这五个 Bean 的时机就是在 AnnotatedBeanDefinitionReader 的构造方法中:

public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry, Environment environment) {
    Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
    Assert.notNull(environment, "Environment must not be null");
    this.registry = registry;
    this.conditionEvaluator = new ConditionEvaluator(registry, environment, null);
    // 就是这里!
    AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
}
public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(
        BeanDefinitionRegistry registry, @Nullable Object source) {
    ...
    Set<BeanDefinitionHolder> beanDefs = new LinkedHashSet<>(8);

    // 注册 org.springframework.context.annotation.internalConfigurationAnnotationProcessor
    // ConfigurationClassPostProcessor 用来处理 Configuration 注解
    if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {
        RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);
        def.setSource(source);
        beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));
    }

    // 注册 org.springframework.context.annotation.internalAutowiredAnnotationProcessor
    // AutowiredAnnotationBeanPostProcessor 用来处理 Autowired 注解
    if (!registry.containsBeanDefinition(AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {
        RootBeanDefinition def = new RootBeanDefinition(AutowiredAnnotationBeanPostProcessor.class);
        def.setSource(source);
        beanDefs.add(registerPostProcessor(registry, def, AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
    }
    
    // 注册 org.springframework.context.annotation.internalCommonAnnotationProcessor
    // CommonAnnotationBeanPostProcessor 用来处理通用注解,例如:@Resource
    if (jsr250Present && !registry.containsBeanDefinition(COMMON_ANNOTATION_PROCESSOR_BEAN_NAME)) {
        RootBeanDefinition def = new RootBeanDefinition(CommonAnnotationBeanPostProcessor.class);
        def.setSource(source);
        beanDefs.add(registerPostProcessor(registry, def, COMMON_ANNOTATION_PROCESSOR_BEAN_NAME));
    }
    
    // 注册 org.springframework.context.event.internalEventListenerProcessor
    // 与 EventListener 有关
    if (!registry.containsBeanDefinition(EVENT_LISTENER_PROCESSOR_BEAN_NAME)) {
        RootBeanDefinition def = new RootBeanDefinition(EventListenerMethodProcessor.class);
        def.setSource(source);
        beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_PROCESSOR_BEAN_NAME));
    }

    // 注册 org.springframework.context.event.internalEventListenerFactory
    // 还是与 EventListener 有关
    if (!registry.containsBeanDefinition(EVENT_LISTENER_FACTORY_BEAN_NAME)) {
        RootBeanDefinition def = new RootBeanDefinition(DefaultEventListenerFactory.class);
        def.setSource(source);
        beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_FACTORY_BEAN_NAME));
    }

    return beanDefs;
}

AnnotationConfigApplicationContext 的刷新

refresh 方法用于启动容器并初始化所有的 Bean。刷新容器这一步骤非常非常重要!也最复杂,所有 Bean 创建都在这个里面。

需要注意的是,这个 refresh 是在 AbstractApplicationContext 类中定义,它是 AnnotationConfigApplicationContext 的父类。

@Override
public void refresh() throws BeansException, IllegalStateException {
    synchronized (this.startupShutdownMonitor) {
        // 做一些准备工作,设置了启动时间,活跃标志位及事件相关内容
        prepareRefresh();
		
        // 获取上下文的核心工厂,这里我们拿到的就是 DefaultListableBeanFactory
        ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

        // 准备工厂,会添加两个 BeanPostProcessor:ApplicationContextAwareProcessor、ApplicationListenerDetector
        prepareBeanFactory(beanFactory);

        try {
            // 这个方法在当前版本是没有任何代码的,可能 Spring 留给后面版本中去扩展
            postProcessBeanFactory(beanFactory);
			
            // 调用 BeanFactoryPostProcessors 的后置处理器
			// 设置执行程序员自定义的 BeanFactoryPostProcessors 和 Spring 内部自己定义的
            invokeBeanFactoryPostProcessors(beanFactory);

            // 注册 BeanPostProcessor 后置处理器
            registerBeanPostProcessors(beanFactory);

            // 为上下文初始化 Message 源,即不同的语言体、国际化处理
            initMessageSource();

            // 初始化应用消息广播
            initApplicationEventMulticaster();

            // 留给子类来初始化其他的 Bean
            onRefresh();

            // 在所有注册的 bean 中查找 listener bean,注册到消息广播器中
            registerListeners();

            // 初始化单例并且非懒加载的 Bean
            finishBeanFactoryInitialization(beanFactory);

            // 完成刷新过程,初始化 LifecycleProcessor 并 start,发布 ContextRefreshedEvent 事件
            finishRefresh();
        } catch (BeansException ex) {
            // 销毁已创建的单例以避免资源悬空。
            destroyBeans();
            // 重置标志位
            cancelRefresh(ex);
            throw ex;
        } finally {
            // 清理缓存
            resetCommonCaches();
        }
    }
}

prepareRefresh

这个方法主要的作用是:准备工作,包括设置 Spring 容器启动时间,是否激活标识位,初始化属性源配置,可以忽略。

obtainFreshBeanFactory

获取上下文的核心工厂,这里我们拿到的就是 DefaultListableBeanFactory,之后的很多操作就是基于此工厂去操作。

prepareBeanFactory(重要)

这个方法是对工厂做一些准备工作,对一些属性进行默认设置,比如设置 Bean 表达式解释器、设置基于 PropertyEditor 的类型转换器、注册一些与系统环境有关的 Bean。

protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {

    // 设置类加载器:存在则直接设置,不存在则新建一个默认类加载器
    beanFactory.setBeanClassLoader(getClassLoader());

    // 设置 EL 表达式解析器(Bean 初始化完成后填充属性时会用到)
    // 默认可以使用 #{bean.xxx} 的形式来调用相关属性值
    beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));

    // 设置属性注册解析器,PropertyEditor 类型的类型转换器
    beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));

    // 添加一个后置处理器,ApplicationContextAwareProcessor,主要是用来处理下面几个 *Aware 的情况
    beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
    // 下面的这些 Aware 处理实际上是用上面的 ApplicationContextAwareProcessor 去处理的,所以这里可以忽略
    // 什么要这样设计?目的就是不在工厂启动的时候注入,而是要在对象创建的时候通过 BeanPostProcessor 去注入。
    // 基于 XML 的历史遗留问题,可能原因是 Aware 是通过 set 注入实现,但若指定自动注入为构造器注入,那么 set 注入在启动阶段就会失效,从而留下隐患。
    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.registerResolvableDependency(BeanFactory.class, beanFactory);
    beanFactory.registerResolvableDependency(ResourceLoader.class, this);
    beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
    beanFactory.registerResolvableDependency(ApplicationContext.class, this);

    // 添加一个后置处理器 ApplicationListenerDetector,用于 Spring 事件的监听处理
    beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));

    // 如果当前 BeanFactory 包含 loadTimeWeaver Bean,说明存在类加载期织入 AspectJ
    // 则把当前 BeanFactory 交给类加载期 BeanPostProcessor 实现类 LoadTimeWeaverAwareProcessor 来处理,从而实现类加载期织入 AspectJ 的目的。
    if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
        beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
        beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
    }

    // 注册环境相关的 Bean,一些系统配置和系统环境信息
    if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {
        // 注册当前容器环境 environment 组件 Bean
        beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());
    }
    if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {
        // 注册系统配置 systemProperties 组件 Bean
        beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());
    }
    if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {
        // 注册系统环境信息 systemEnvironment 组件 Bean
        beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());
    }
}

postProcessBeanFactory

这个方法在当前版本的 Spring 是没用任何代码的,可能 Spring 期待在后面的版本中去扩展吧,忽略。

invokeBeanFactoryPostProcessors(重要)

调用 BeanFactoryPostProcessors 的后置处理器,执行程序员自定义的 BeanFactoryPostProcessors 和 Spring 内部自己定义的。到目前为止,我们只有一个 ConfigurationClassPostProcessor 是 BeanFactoryPostProcessor 类型。

protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
    // 这个地方需要注意 getBeanFactoryPostProcessors() 方法是获取手动给 Spring 容器中添加的 BeanFactoryPostProcessor(程序员自定义)
    PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());

    if (beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
        beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
        beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
    }
}

getBeanFactoryPostProcessors() 方法是获取手动给 Spring 容器中添加的 BeanFactoryPostProcessor(程序员自定义)如何理解呢?此方法获取的是程序员自己创建的,并且程序员需要在容器启动的时候手动调用 AnnotationConfigApplicationContext.addBeanFactoryPostProcessor() 方法添加到上下文。如下代码:

AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext();
ac.register(AppConfig.class);
// 手动添加 BeanFactoryPostPorcessor
ac.addBeanFactoryPostProcessor(new TestBeanFactoryPostPorcessor());
ac.refresh();

接下来分析 PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors 这个方法,此处就是 BeanFactoryPostProcessor 处理的核心所在:

注意下面方法的参数 beanFactoryPostProcessors 是程序员在创建上下文的时候手动添加的(context.addBeanFactoryPostProcessor(XXX.class)),这种 beanFactoryPostProcessor 是不会创建 BD 注册的,而是会直接调用。
为什么手动 add 的就不会再注册 BD?注册的目的是为了创建对象然后执行,这里 add 的时候直接添加的就是对象了,所以没必要再创建 BD了。

// 如果程序员没有自己手动添加,方法的第二个参数 beanFactoryPostProcessors 传进来为空
public static void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory, 
                                                   List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {

    // 定义一个 Set,用于存放已经执行过的 Bean 的名字
    Set<String> processedBeans = new HashSet<>();

    // 这地方条件为真,因为 DefaultListableBeanFactory 实现了 BeanDefinitionRegistry 接口,所以进入
    if (beanFactory instanceof BeanDefinitionRegistry) {

        BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;

        // 定义两个 List,一个存放 BeanFactoryPostProcessor,一个存放 BeanDefinitionRegistryPostProcessor
        // 此 List 是存放程序员自定义的 BeanFactoryPostProcessor
        List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>();

        // 这个里面存放的是程序员自定义的和 Spring 容器提供的 BeanDefinitionRegistryPostProcessor
        List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>();

        // 程序员自定义的 beanFactoryPostProcessors,此处传进来为空
        for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
            if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
                BeanDefinitionRegistryPostProcessor registryProcessor = (BeanDefinitionRegistryPostProcessor) postProcessor;
                // 执行 BeanDefinitionRegistryProcessor 的 postProcessBeanDefinitionRegistry 方法(此处是自定义的)
                registryProcessor.postProcessBeanDefinitionRegistry(registry);
                // 加入到 registryProcessors 集合中
                registryProcessors.add(registryProcessor);
            } else {
                // 如果不是 BeanDefinitionRegistryPostProcessor 这种类型,加入到 regularPostProcessors 集合中
                regularPostProcessors.add(postProcessor);
            }
        }

        // 这个 currentRegistryProcessors 存放的是 Spring 内部自己实现了 BeanDefinitionRegistryPostProcessor 接口的对象
        List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();

        // 从容器中获取 BeanDefinitionRegistryPostProcessor 类型,这地方只有一个 ConfigurationClassPostProcessor
        // 因为只有它实现了 BeanDefinitionRegistryPostProcessor 接口
        // 还记得这个类是什么时候加到 Spring 容器中的么?是 Spring 默认在最开始自己创建 Reader 读取器的时候注册的
        String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);

        // 这个 ConfigurationClassPostProcessor 有哪些功能呢?这个类就非常非常重要了
        // Spring 工厂需要去解析、去扫描等等功能,而这些功能都是需要在 Spring 工厂初始化完成之前执行
        // 要么在工厂最开始的时候、要么在工厂初始化之中,反正不能在之后,因为如果在之后就没有意义,因为那个时候已经需要使用工厂了
        // 所以 Spring 在一开始就注册了一个 BeanFactoryPostProcessor,用来插手 Spring 工厂的实例化过程
        for (String ppName : postProcessorNames) {
            // ConfigurationClassPostProcessor 实现了 PriorityOrdered 接口
            if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
                // 此处 getBean 执行了 ConfigurationClassPostProcessor 的实例化,创建出了真正的对象
                currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
                processedBeans.add(ppName);
            }
        }
        // 排序不重要,况且 currentRegistryProcessors 这里也只有一个数据
        sortPostProcessors(currentRegistryProcessors, beanFactory);
        // 合并 List 不重要,为什么要合并?因为还有程序员自己定义的
        registryProcessors.addAll(currentRegistryProcessors);
        
        // 最重要!注意这里是方法调用,执行 currentRegistryProcessors 中所有的 BeanDefinitionRegistryPostProcessor
        // 也就是 ConfigurationClassPostProcessor 中的 postProcessBeanDefinitionRegistry() 方法
        invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
        
        // 执行完成了所有 BeanDefinitionRegistryPostProcessor,这个 List 只是一个临时变量,故而要清除
        currentRegistryProcessors.clear();
        
        // 到此处已经完成了所有类的扫描工作,因为扫描是在 ConfigurationClassPostProcessor 中的 postProcessBeanDefinitionRegistry 方法完成

        // 程序员可能自己有创建了 BeanDefinitionRegistryPostProcessor 类,是用 @Component 注解修饰的
        // 所以这个地方被容器扫码到了,所以又去拿一遍,如果程序员没有自己创建,那还是拿到了 ConfigurationClassPostProcessor 这个类
        postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
        for (String ppName : postProcessorNames) {
            // ConfigurationClassPostProcessor 已经执行过,不会重复执行,这里执行的主要是通过 @Component 注解修饰的,并且加了排序策略!
            // 注意,这里是执行的程序员定义的 BeanDefinitionRegistryPostProcessor 类型
            if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) {
                currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
                processedBeans.add(ppName);
            }
        }
        // 此处 currentRegistryProcessors 为空,所以代码并没有啥意思,但这地方是不是 Spring 的一个扩展点呢?实现 Ordered.class 接口?
        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;
            // 还是拿到这个 ConfigurationClassPostProcessor,但 processedBeans 集合里已经包含这个类啦,所以也不会执行
            // 这里主要执行通过 @Component 注解修饰的,并且没有加入排序策略!
            // 注意,这里是执行的程序员定义的 BeanDefinitionRegistryPostProcessor 类型
            postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
            for (String ppName : postProcessorNames) {
                // processedBeans 集合里已包含,所以条件不成立
                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 的子类 BeanDefinitionRegistryPostProcessor 中 postProcessBeanDefinitionRegistry() 方法
        // 这里是执行的是 BeanFactoryPostProcessor 的 postProcessBeanFactory() 方法
        // 这个 registryProcessors 里面存的是啥?程序员自定义的和 Spring 内部添加的 BeanDefinitionRegistryPostProcessor
        invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
        // 这里调用的是程序员自定义的 BeanFactoryPostProcessor,这集合里并没有数据
        // 这个 regularPostProcessors 里面存的是啥?程序员自定义的 BeanFactoryPostProcessor
        invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
    } else {
        invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);
    }

    // 此处拿到的是实现 BeanFactoryPostProcessor 接口的类,包括 ConfigurationClassPostProcessor 和程序员自定义的 BeanFactoryPostProcessor
    // 刚刚已经已进行的 @Component 等注解的扫描工作,所以这里已经可以拿到程序员自定义的 BeanFactoryPostProcessor
    String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);

    // 将拿到的所有 BeanFactoryPostProcessor 进行分组,分别存储在三个 List,分为 PriorityOrdered 实现类、Ordered 实现类和没有排序策略的 
    List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
    List<String> orderedPostProcessorNames = new ArrayList<>();
    List<String> nonOrderedPostProcessorNames = new ArrayList<>();
    
    for (String ppName : postProcessorNames) {
        // 此处 processedBeans 里面已经包含了 ConfigurationAnnotationProcessor,直接跳过
        if (processedBeans.contains(ppName)) {
        } 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
    sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
    invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);

    // 再排序并调用所有实现 Ordered 接口的 BeanFactoryPostProcessor
    List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<>();
    for (String postProcessorName : orderedPostProcessorNames) {
        orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
    }
    sortPostProcessors(orderedPostProcessors, beanFactory);
    invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);

    // 最后再调用没有排序策略的 BeanFactoryPostProcessor
    List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<>();
    for (String postProcessorName : nonOrderedPostProcessorNames) {
        nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
    }
    invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);

    // 清除元数据缓存(mergedBeanDefinitions、allBeanNamesByType、singletonBeanNamesByType)
    // 因为后处理器可能已经修改了原始元数据,例如替换值中的占位符...
    beanFactory.clearMetadataCache();
}

总结一下:

首先处理 BeanDefinitionRegistryPostProcessor 类型:

  1. 先执行程序员自定义的 BeanDefinitionRegistryPostProcessor#postProcessBeanDefinitionRegistry 方法

  2. 再执行 Spring 自己提供的 BeanDefinitionRegistryPostProcessor#postProcessBeanDefinitionRegistry 方法(ConfigurationClassPostProcessor)

  3. 然后再执行被 Spring 扫描到的 BeanDefinitionRegistryPostProcessor#postProcessBeanDefinitionRegistry 方法,先执行实现了 Ordered 接口的,再执行没有实现 Ordered 接口的。

    多个 BeanFactoryPostProcessor 实例可能会存在相互依赖关系。因此,了解并控制它们的执行顺序非常重要。可以实现 Ordered 接口或 PriorityOrdered 接口来指定执行顺序。官方文档中明确指出 BeanFactoryPostProcessor 不能使用 @Order 注解。

    BeanPostProcessor beans that are autodetected in an ApplicationContext will be ordered according to PriorityOrdered and Ordere semantics. In contrast, BeanPostProcessor beans that are registered programmatically with a BeanFactory will be applied in the order of registration; any ordering semantics expressed through implementing the PriorityOrdered or Ordered interface will be ignored for programmatically registered post-processors. Furthermore, the @Order annotation is not taken into account for BeanPostProcessor beans.

  4. 执行程序员自定义且手动放入上下文的、Spring 内部提供的、通过注解扫描出的 BeanDefinitionRegistryPostProcessor#beanFactoryPostProcessors 方法

然后处理 BeanFactoryPostProcessor 类型:

  1. 执行程序员自定义且手动放入上下文的 BeanFactoryPostProcessor#beanFactoryPostProcessors 方法
  2. 从容器中拿到所有的 BeanFactoryPostProcessor 进行分组(已经执行过的直接跳过):PriorityOrdered 类型、Ordered 类型、没有排序策略的三个 List。
  3. 依次执行这三个 List,priorityOrderedPostProcessors -> orderedPostProcessorNames -> nonOrderedPostProcessorNames。
  4. 最后清洗元数据缓存,因为后处理器可能已经修改了原始元数据。

截止到目前,只是完成了 BeanDefinition 的注册,并没有开始实例化其他的 Bean 对象,例如 XXXService、XXXController、XXXMapper。其实这里已经是把自定义的 BeanFactoryPostProcessor 实例化了,因为要去使用它。

registerBeanPostProcessors

注册 BeanPostProcessor,找出前面生成的所有 beandefinition 是 BeanPostProcessor 接口的实现类,包括自定义实现 BeanPostProcessor 接口类,且按照实现 PriorityOrdered、Ordered 接口、未实现 PriorityOrder&Ordeded、实现 MergedBeanDefinitionPostProcessor 的顺序排序后放入 beanfactory 的 beanPostProcessors 属性中。

此过程还会在 beanfactory 的 beanPostProcessors 属性中放入 ApplicationListenerDetector 对象,这个步骤其实在 prepareBeanFactory() 进行过一次,这样做的目的是为将事件广播的放在所有的 BeanPostProcessor 类之后处理。

这个步骤还是非常的简单,其实就是按照顺序把前面创建的所有 BeanPostProcessor 的实例放入工厂的 beanPostProcessors 属性中。

initMessageSource

处理国际化相关的操作,一般用于 Web 开发 i18n,不过一般也不怎么用,可以忽略。

initMessageSource 方法主要负责初始化 ApplicationContext 中的消息源。为 Spring 应用程序提供了国际化和本地化消息支持的基础。

  1. 获取 MessageSource 对象:首先,ApplicationContext 会尝试从已经注册的 bean 中查找类型为 MessageSource 的 bean。找到了直接使用,找不到则会创建一个新的 DelegatingMessageSource 对象。
  2. 设置 Parent MessageSource:如果当前 ApplicationContext 有父容器(parent context),则会将父容器中的 MessageSource 设置为当前 MessageSource 的父级,以支持层次化的消息源查找。
protected void initMessageSource() {
    ConfigurableListableBeanFactory beanFactory = getBeanFactory();
    // 这个 MESSAGE_SOURCE_BEAN_NAME 就是 "messageSource"
    if (beanFactory.containsLocalBean(MESSAGE_SOURCE_BEAN_NAME)) {
        this.messageSource = beanFactory.getBean(MESSAGE_SOURCE_BEAN_NAME, MessageSource.class);
        // 如果找到了名为 "messageSource" 的 bean,则直接使用它
        if (this.parent != null && this.messageSource instanceof HierarchicalMessageSource) {
            HierarchicalMessageSource hms = (HierarchicalMessageSource) this.messageSource;
            if (hms.getParentMessageSource() == null) {
                // 如果有父容器,则会将父容器中的 MessageSource 设置为当前 MessageSource 的父级,以支持层次化的消息源查找
                hms.setParentMessageSource(getInternalParentMessageSource());
            }
        }
        if (logger.isTraceEnabled()) {
            logger.trace("Using MessageSource [" + this.messageSource + "]");
        }
    }
    else {
        // 创建一个 DelegatingMessageSource 对象,并注册为单例 bean
        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 + "]");
        }
    }
}

initApplicationEventMulticaster

主要是处理事件的广播操作,用的比较少,SpringCloud 中会涉及。

initApplicationEventMulticaster 方法主要是为上下文初始化应用事件广播器,ApplicationEventMulticaster 负责管理和分发应用程序中的事件,它是 Spring 事件驱动模型的核心组件之一。

和上面的 initMessageSource 步骤类似,首先尝试从容器中获取现有的 ApplicationEventMulticaster bean,如果不存在则创建一个新的 SimpleApplicationEventMulticaster 实例,并注册为单例 Bean。

protected void initApplicationEventMulticaster() {
    ConfigurableListableBeanFactory beanFactory = getBeanFactory();
    if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) {
        // 尝试获取现有的事件广播器,默认名称为 "applicationEventMulticaster"
        this.applicationEventMulticaster =
            beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class);
        if (logger.isTraceEnabled()) {
            logger.trace("Using ApplicationEventMulticaster [" + this.applicationEventMulticaster + "]");
        }
    }
    else {
        // 不存在已有 Bean,则创建一个新的广播器
        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() + "]");
        }
    }
}

onRefresh

空方法,忽略。

registerListeners

也是事件相关的操作,用来注册监听器,SpringCloud 中会涉及。

registerListeners 方法负责将所有的 ApplicationListener 注册到 ApplicationContext 的事件广播器中,从而确保应用程序中的事件能够被正确监听和处理。这一步骤对于支持 Spring 的事件驱动模型非常重要,能够让应用程序各个组件之间实现松耦合的通信。解析 registerListeners 方法:

  1. 获取所有的 ApplicationListener:首先通过调用 getApplicationListeners 方法获取所有在 ApplicationContext 中注册的 ApplicationListener 实例。
  2. 将监听器添加到事件广播器:遍历所有获取到的 ApplicationListener,并将它们通过 getApplicationEventMulticaster().addApplicationListener(listener) 方法添加到 ApplicationContext 的事件广播器中。
  3. 处理早期的应用程序事件:如果在容器刷新过程中收到了早期的应用程序事件(early application events),这些事件在注册监听器之前就被存储在 earlyApplicationEvents 中。在这一步骤中,会将这些早期事件逐个通过事件广播器的 multicastEvent 方法广播出去。

finishBeanFactoryInitialization(重要)

通过 Spring 的 BeanFactory 创建单例的非延迟加载的 Bean,Spring 在这个步骤之前准备了什么?

  1. 通过 ConfigurationClassPostProcesser 创建和注册 BeanDefinition,用于创建 Bean 的模板。
  2. 准备一些列的 BeanPostProcesser 用于在创建 Bean 的同时加工。

在 Spring Framework 中,finishBeanFactoryInitialization 方法是 AbstractApplicationContext 类中的一个关键步骤,它负责完成 BeanFactory 的初始化工作,特别是实例化所有的非延迟加载(non-lazy-init)的单例 Bean。

这里就是拿到所有已经注册的 BeanDefinition,循环去实例化,实例化过程要进行判断(不能是抽象、不能是懒加载、并且是单例)

protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
    // 处理类型转换器,将配置文件或者通过接口获取的 String -> 对象中的类型
    // 注意这里的转换器的 Bean 的名字,必须叫做 convertionService,通过 @Component 或 @Bean 时候要指定名称
    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));
    }
    // 注册嵌入值解析器,用于解析 @Value(${表达式})
    if (!beanFactory.hasEmbeddedValueResolver()) {
        beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal));
    }
    // 尽早实例化 LoadTimeWeaverAware 类型的 Bean
    String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
    for (String weaverAwareName : weaverAwareNames) {
        getBean(weaverAwareName);
    }
    // Stop using the temporary ClassLoader for type matching.
    beanFactory.setTempClassLoader(null);
    // 将 beanfactory 的属性 configurationFrozen 变为 true,意味着类解析已完成
    // 冻结 BeanDefinition 的修改,不然 BeanFactoryPostProcesser 再次修改 BD,否则会影响 Bean 的创建
    beanFactory.freezeConfiguration();
    // 根据所有内容 beandefinition 加载非 lazy-init、非抽象 bean,通过 getBean 方法来实进行实例化
    // 这里是核心步骤
    beanFactory.preInstantiateSingletons();
}
public void preInstantiateSingletons() throws BeansException {
    if (logger.isTraceEnabled()) {
        logger.trace("Pre-instantiating singletons in " + this);
    }

    // 获取所有的 Bean 定义
    List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);

    // 这里就是拿到所有已经注册的 BeanDefinition,循环去实例化,实例化过程要进行判断(不能是抽象、不能是懒加载、并且是单例)
    for (String beanName : beanNames) {
        // 合并父子 Bean 的信息
        RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
        if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
            // 不能是抽象、不能是懒加载、并且是单例
            if (isFactoryBean(beanName)) {
                // FactoryBean 情况处理
                Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
                if (bean instanceof FactoryBean) {
                    final 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 {
                // 获取普通的 Bean
                getBean(beanName);
            }
        }
    }

    // 如果 Bean 实现了 SmartInitializingSingleton 接口,则在这里回调初始化完成方法
    for (String beanName : beanNames) {
        Object singletonInstance = getSingleton(beanName);
        if (singletonInstance instanceof SmartInitializingSingleton) {
            final SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
            if (System.getSecurityManager() != null) {
                AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
                    smartSingleton.afterSingletonsInstantiated();
                    return null;
                }, getAccessControlContext());
            }
            else {
                smartSingleton.afterSingletonsInstantiated();
            }
        }
    }
}

finishRefresh

finishRefresh 方法主要是发布事件,包括清除上下文资源缓存,为上下文初始化生命周期处理器,发布最终事件。它是 Spring Framework 中 ApplicationContext 刷新过程的最后一步,它负责确保容器刷新后的稳定性和一致性,并且通知所有相关的组件和监听器,以便它们可以执行相应的后续操作。

protected void finishRefresh() {
    // 清除一些资源缓存
    clearResourceCaches();

    // 初始化生命周期处理器,允许它们执行刷新后的回调逻辑
    initLifecycleProcessor();

    // 设置容器状态为活跃状态
    getLifecycleProcessor().onRefresh();

    // 发布容器刷新完成的最终事件,通知相关的监听器
    publishEvent(new ContextRefreshedEvent(this));

    // Participate in LiveBeansView MBean, if active.
    LiveBeansView.registerApplicationContext(this);
}
  • 21
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值