SpringBoot 系统初始化器

212 阅读1分钟

仅供个人学习记录使用

来自于慕课网《图解+仿写 新手都能学懂的SpringBoot源码课》课程

Reference:全方位深入解析最新版SpringBoot源码-慕课网实战 (imooc.com)

章节目录:

一、系统初始化器介绍

二、SpringFactoriesLoader介绍

三、系统初始化器原理解析

四、总结

系统初始化器介绍

一、类名:ApplicationContextInitializer

二、介绍:Spring容器刷新之前执行的一个回调函数

三:作用:向SpringBoot容器中注册属性

四:使用:继承接口自定义实现

自定义系统初始化器:

@Order(1)
public class FirstInitializer implements ApplicationContextInitializer<ConfigurableApplicationContext> {
    @Override
    public void initialize(ConfigurableApplicationContext applicationContext) {
        ConfigurableEnvironment configurableEnvironment = applicationContext.getEnvironment();
        Map<String, Object> map = new HashMap<>();
        map.put("key1", "value1");
        MapPropertySource mapPropertySource = new MapPropertySource("firstInitializer", map);
        configurableEnvironment.getPropertySources().addLast(mapPropertySource);
        System.out.println("run firstInitializer");
    }
}

注册系统初始化器方式:

一、resources 下 META-INF 文件夹下创建 spring.factories 文件

org.springframework.context.ApplicationContextInitializer = com.mooc.sb2.initializer.FirstInitializer

二、SpringApplication addInitializers 硬编码添加

SpringApplication springApplication = new SpringApplication(Sb2Application.class);
springApplication.addInitializers(new SecondInitializer());
springApplication.run(args);

三、在resources 下 application.properties 文件中注册

context.initializer.classes = com.mooc.sb2.initializer.ThirdInitializer

Tips:

  • 都要实现 ApplicationContextInitializer 接口

  • order 值越小越先执行

  • application.properties 中定义的优先于其他方式

SpringFactoriesLoader 介绍

  1. 框架内部使用的通用工厂加载机制

  2. 从 classpath 下多个 jar 包特定的位置读取文件并初始化类

  3. 文件内容必须是kv形势,即 properties 类型

  4. key 是全限定名(抽象类|接口)、value 是实现,多个实现用“,”分隔

源码部分

image.png

image.png

image.png

private <T> Collection<T> getSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes, Object... args) {
    // 获取类加载器
    ClassLoader classLoader = getClassLoader();
    // 获取系统初始化器名称
    Set<String> names = new LinkedHashSet<>(SpringFactoriesLoader.loadFactoryNames(type, classLoader));
    // 获取系统初始化器实例
    List<T> instances = createSpringFactoriesInstances(type, parameterTypes, classLoader, args, names);
    // 给系统初始化器实例排序
    AnnotationAwareOrderComparator.sort(instances);
    return instances;
}

获取系统初始化器名称:

image.png

image.png

获取系统初始化器实例:

获取全限定类名、获取构造器、通过 BeanUtils 与构造器获取实例

image.png

SpringFactoriesLoader 作用

  • SpringBoot 框架中从类路径 jar 包中读取特定文件实现扩展类的载入

image.png

loadFactories流程

image.png

SpringApplicationInitializer

  • 上下文刷新即 refresh 方法前调用

  • 用来编码设置一些属性变量通常用在 web 环境中

  • 可以通过 order 接口进行排序

SpringApplicationInitializer 调用流程

image.png

image.png

image.png

image.png

为何 thirdInitializer 先执行?

DelegatingApplicationContextInitializer order 为0,优先执行

image.png

image.png

image.png

image.png

image.png

调用流程

image.png

实现原理:

  • 定义在 spring.factories 文件中被 SpringFactoriesLoader 发现注册

  • SpringApplication 初始化完毕后手动添加

  • 定义成环境变量被 DelegatingApplicationContextInitializer 发现注册