自学内容网 自学内容网

Springboot中ApplicationContextInitializer的使用及源码分析

一、认识ApplicationContextInitializer

1、ApplicationContextInitializer的作用

ApplicationContextInitializer接口的执行时机:用于在刷新之前初始化Spring ConfigurableApplicationContext的回调接口。

通常在需要对应用程序上下文进行一些编程初始化的web应用程序中使用。例如,根据上下文环境注册属性源或激活概要文件

2、认识ApplicationContextInitializer接口

ApplicationContextInitializer接口只有一个方法,实现该方法会获得一个ConfigurableApplicationContext的回调。

@FunctionalInterface
public interface ApplicationContextInitializer<C extends ConfigurableApplicationContext> {

void initialize(C applicationContext);

}

3、ApplicationContextInitializer的常用用法

(1)注册BeanFactoryPostProcessor

在这里插入图片描述

(2)注册ApplicationListener监听器

在这里插入图片描述

(3)处理Environment运行环境(获取、修改配置等)

在这里插入图片描述
在这里插入图片描述

(4)设置ApplicationContext的parent

在这里插入图片描述

(5)注册Bean

在这里插入图片描述

(6)注册BeanPostProcessor

在这里插入图片描述

二、使用ApplicationContextInitializer

1、定义ApplicationContextInitializer实现类

public class FirstInitializer implements ApplicationContextInitializer {

    @Override
    public void initialize(ConfigurableApplicationContext applicationContext) {
        ConfigurableEnvironment environment = applicationContext.getEnvironment();

        Map<String, Object> map = new HashMap<>();
        map.put("key1", "First");

        MapPropertySource mapPropertySource = new MapPropertySource("firstInitializer", map);
        environment.getPropertySources().addLast(mapPropertySource);

        System.out.println("run firstInitializer");
    }

}

public class SecondInitializer implements ApplicationContextInitializer {

    @Override
    public void initialize(ConfigurableApplicationContext applicationContext) {
        ConfigurableEnvironment environment = applicationContext.getEnvironment();

        Map<String, Object> map = new HashMap<>();
        map.put("key1", "Second");

        MapPropertySource mapPropertySource = new MapPropertySource("secondInitializer", map);
        environment.getPropertySources().addLast(mapPropertySource);

        System.out.println("run secondInitializer");
    }

}

public class ThirdInitializer implements ApplicationContextInitializer {

    @Override
    public void initialize(ConfigurableApplicationContext applicationContext) {
        ConfigurableEnvironment environment = applicationContext.getEnvironment();

        Map<String, Object> map = new HashMap<>();
        map.put("key1", "Third");

        MapPropertySource mapPropertySource = new MapPropertySource("thirdInitializer", map);
        environment.getPropertySources().addLast(mapPropertySource);

        System.out.println("run thirdInitializer");
    }

}

2、注册ApplicationContextInitializer

(1)在resources/META-INF/spring.factories配置

org.springframework.context.ApplicationContextInitializer=com.learn.springboot.initializer.FirstInitializer

(2)代码注册

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

(3)配置文件注册

context.initializer.classes=com.learn.springboot.initializer.ThirdInitializer

3、查看结果

可以看到配置生效了,并且三种配置优先级不一样,配置文件优先级最高,spring.factories 其次,代码最后。

run thirdInitializer
run firstInitializer
run secondInitializer

4、设置执行顺序

可以通过@Order或者实现org.springframework.core.Ordered接口并重写setOrder方法设置顺序,@Order 值越小,执行优先级越高。

三、源码分析

springboot启动流程,手把手打断点一步步看运行步骤

1、加载ApplicationContextInitializer

在Springboot启动时,会加载所有META-INF/spring.factories中定义的ApplicationContextInitializer
在这里插入图片描述
如果用SpringApplication的addInitializers方法添加,相当于直接添加到这个List中:
在这里插入图片描述

2、执行时机

在springboot启动,调用prepareContext方法时:
在这里插入图片描述
在这里插入图片描述
所以说,initialize方法是在IOC容器启动之前执行的,此时的容器还未初始化,只能做一些容器启动前的准备工作。

参考资料

https://zhuanlan.zhihu.com/p/509824476
https://mp.weixin.qq.com/s/_kTPz22QY9fZXmyYtE-Ulw


原文地址:https://blog.csdn.net/A_art_xiang/article/details/136346884

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!