SpringCloud源码解析(2)--ApplicationContextInitializer配置与原理

前言

上文粗略的看了springboot启动相关的源码,这次我们来看SpringApplication构造方法中初始化的ApplicationContextInitializer的作用 ApplicationContextInitializer主要用于在spring创建上下文之前调用prepareContext的时候触发一系列操作主要是对上下文进行配置 实现了ApplicationContextInitializer接口的类都会在spring启动调用prepareContext的时候执行

ApplicationContextInitializer三种配置方式

1-项目配置文件配置

1-bootstrap.yml配置或者application.yml进行配置

如图

代码如下

/**
 * 项目配置文件注入方式
 */
public class TestInit2 implements ApplicationContextInitializer {
	@Override
	public void initialize(ConfigurableApplicationContext configurableApplicationContext) {
		System.out.println("TestInit2-----------项目配置文件注入方式");
	}
}

/**
 * application.yml项目配置文件注入方式
 */
public class TestInit2_1 implements ApplicationContextInitializer {
	@Override
	public void initialize(ConfigurableApplicationContext configurableApplicationContext) {
		System.out.println("TestInit2-1-----------项目配置文件注入方式");
	}
}
复制代码

2-项目代码配置

也可以在项目中进行配置添加如下

@SpringBootApplication
public class TestServerApplication {
	public static void main(String[] args) {
		SpringApplication springApplication = new SpringApplication(TestServerApplication.class);
		springApplication.addInitializers(new TestInit0());  //添加ApplicationContextInitializer
		ConfigurableApplicationContext context = springApplication.run(args);
		context.close();
	}
}
复制代码

3-spring工厂配置文件配置

也可以在项目中通过spring.factories进行配置 主要是在项目的resources下添加如下文件

在spring.factories中进行如下配置

org.springframework.context.ApplicationContextInitializer=com.tuhuanjk.cloud.config.access.TestInit1
复制代码

执行结果输出如下

···

···

执行结果解析

执行顺序

可以在代码上使用@Order注解进行配置执行顺序 @Order的value值越小越早执行

ApplicationContextInitializer三种配置执行的默认先后顺序及源码位置

由执行结构可知在spring.factories中配置的类会加载并执行两次 同时执行默认顺序为 1 bootstrap中配置 2 spring.factories中配置 3 aoolication中配置 4 spring.factories中配置 5 代码中配置

这是因为spring boot会在创建application上下文时通知BootstrapApplicationListener并在BootstrapApplicationListener中通过SpringApplicationBuilder创建一次bootstrap的ConfigurableApplicationContext上下文并调用run方法 这里就会输出 1 和 2 然后再接着创建application上下文 这里就会输出3,4,5 具体原理可以参考我的另一篇文章 www.jianshu.com/p/f038d9e12…

1-在spring.factories中配置的类最先加载

通过SpringApplication构造方法中的如下代码进行读取配置文件并加载入SpringApplication的initializers集合(ArrayList)

 this.setInitializers(this.getSpringFactoriesInstances(ApplicationContextInitializer.class));
复制代码
2-在boostrap中配置的加载顺序为第二

在创建bootstrap上下文时先通过ConfigFileApplicationListener将配置读入内存然后再通过DelegatingApplicationContextInitializer进行加载配置的类并调用initialize方法进行执行关键代码在DelegatingApplicationContextInitializer的initialize方法中如下代码

DelegatingApplicationContextInitializer的方法
 public void initialize(ConfigurableApplicationContext context) {
        ConfigurableEnvironment environment = context.getEnvironment();
        List<Class<?>> initializerClasses = this.getInitializerClasses(environment);
        if (!initializerClasses.isEmpty()) {
            this.applyInitializerClasses(context, initializerClasses);
        }

    }

获取在bootstrap中配置的ApplicationContextInitializer类
    private List<Class<?>> getInitializerClasses(ConfigurableEnvironment env) {
        String classNames = env.getProperty("context.initializer.classes");
        List<Class<?>> classes = new ArrayList();
        if (StringUtils.hasLength(classNames)) {
            String[] var4 = StringUtils.tokenizeToStringArray(classNames, ",");
            int var5 = var4.length;

            for(int var6 = 0; var6 < var5; ++var6) {
                String className = var4[var6];
                classes.add(this.getInitializerClass(className));
            }
        }

        return classes;
    }
执行在bootstrap中配置的ApplicationContextInitializer类
 private void applyInitializerClasses(ConfigurableApplicationContext context, List<Class<?>> initializerClasses) {
        Class<?> contextClass = context.getClass();
        List<ApplicationContextInitializer<?>> initializers = new ArrayList();
        Iterator var5 = initializerClasses.iterator();

        while(var5.hasNext()) {
            Class<?> initializerClass = (Class)var5.next();
           //将配置的类实例化并放入spring容器
            initializers.add(this.instantiateInitializer(contextClass, initializerClass));
        }
       //回调对应的initialize方法
        this.applyInitializers(context, initializers);
    }

复制代码
3-application.yml中配置的加载顺序为第三

加载代码和在bootstrap.yml中配置 加载方式一样,只是因为bootstrap.yml中配置的 在创建的bootstrap上下时候就执行了而在application.yml中配置的在创建application上下文时候才执行 所以有先后顺序

4-代码中配置的加载顺序为第四

通过代码中显示的配置直接将类加载入SpringApplication的initializers集合 如下代码

springApplication.addInitializers(new TestInit0());
复制代码

转载于:https://juejin.im/post/5befbcd651882516b9378875

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值