美文网首页
SpringBoot源码分析之系统初始化器

SpringBoot源码分析之系统初始化器

作者: handsomemao666 | 来源:发表于2020-08-23 16:30 被阅读0次

SpringBoot系统初始化器作用

  • 上下文刷新即refresh方法前调用
  • 通常用在web环境中设置一些属性变量
  • 可以通过order接口进行排序

1. 实现方式

  • 实现ApplicationContextInitializer类
@Order(1)
public class FirstInitializer implements ApplicationContextInitializer<ConfigurableApplicationContext> {
    @Override
    public void initialize(ConfigurableApplicationContext applicationContext) {
        ConfigurableEnvironment environment = applicationContext.getEnvironment();
        environment.setRequiredProperties("mooc");
        Map<String, Object> map = new HashMap<>();
        map.put("key1", "value1");
        MapPropertySource mapPropertySource = new MapPropertySource("firstInitializer", map);
        environment.getPropertySources().addLast(mapPropertySource);
        System.out.println("run firstInitializer");
    }
}
  • 在/resources/META-INF新建spring.factories配置文件
    key值为:org.springframework.context.ApplicationContextInitializer
    value值为具体的实现类:com.mooc.sb2.initializer.FirstInitializer
org.springframework.context.ApplicationContextInitializer=com.mooc.sb2.initializer.FirstInitializer

2. 源码分析

注册系统初始化器
在创建SpringApplication的时候,会注册系统初始化器

public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
        this.resourceLoader = resourceLoader;
        Assert.notNull(primarySources, "PrimarySources must not be null");
        this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
        this.webApplicationType = WebApplicationType.deduceFromClasspath();
        //注册系统初始化器
        setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
        setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
        this.mainApplicationClass = deduceMainApplicationClass();
    }

在注册系统初始化器时,通过SpringFactoriesLoader来加载配置在spring.factories配置文件中的系统初始化器。
SpringFactoriesLoader是spring内部使用的通用工厂加载机器,从classpath下的多个jar包读取/resources/META-INF/spring.factories内容。文件内容必须是kv形式,key为全限定名,value为实现,多个实现用逗号进行分割。
调用系统初始化器
在refresh方法之前,prepareContext方法中会调用系统初始化器,源码如下:

private void prepareContext(ConfigurableApplicationContext context, ConfigurableEnvironment environment,
            SpringApplicationRunListeners listeners, ApplicationArguments applicationArguments, Banner printedBanner) {
        context.setEnvironment(environment);
        postProcessApplicationContext(context);
        //调用系统初始化器
        applyInitializers(context);
        listeners.contextPrepared(context);
        if (this.logStartupInfo) {
            logStartupInfo(context.getParent() == null);
            logStartupProfileInfo(context);
        }
        // Add boot specific singleton beans
        ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
        beanFactory.registerSingleton("springApplicationArguments", applicationArguments);
        if (printedBanner != null) {
            beanFactory.registerSingleton("springBootBanner", printedBanner);
        }
        if (beanFactory instanceof DefaultListableBeanFactory) {
            ((DefaultListableBeanFactory) beanFactory)
                    .setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
        }
        // Load the sources
        Set<Object> sources = getAllSources();
        Assert.notEmpty(sources, "Sources must not be empty");
        load(context, sources.toArray(new Object[0]));
        listeners.contextLoaded(context);
    }

相关文章

网友评论

      本文标题:SpringBoot源码分析之系统初始化器

      本文链接:https://www.haomeiwen.com/subject/wkoijktx.html