记一次实现ApplicationContextInitializer的方法(SpringBoot)

最近再看SpringBoot的源码,在调用refreshContext(context)之前,会对ApplicationContextInitializer的实现类等进行调用.所以写一篇文章来进行记录


话不多话,先上代码,当然这里直接实现,在SpringBoot并不会启动,我们采用第一种方式来指定

No 1 :

package com.yang.threadspringcase.initializer;

/*
 *@author:BaoYang
 *@Date: 2020/2/26
 *@description:
 */

import org.springframework.context.ApplicationContextInitializer;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.MapPropertySource;

import java.util.HashMap;
import java.util.Map;

public class FirstInitializer implements ApplicationContextInitializer<ConfigurableApplicationContext>
{
    @Override
    public void initialize(ConfigurableApplicationContext applicationContext)
    {
        ConfigurableEnvironment contextEnvironment = applicationContext.getEnvironment();
        // contextEnvironment.setRequiredProperties("yang");
        Map<String,Object> map = new HashMap<>();
        map.put("key1","value1");
        MapPropertySource mapPropertySource = new MapPropertySource("firstInitializer",map);
        contextEnvironment.getPropertySources().addLast(mapPropertySource);

        System.out.println("FirstInitializer  Add ....");
    }
}

这里我们在resources下面,创建一个META-INF目录,

org.springframework.context.ApplicationContextInitializer=com.yang.threadspringcase.initializer.FirstInitializer

然后使用这句话来指定即可,这是第一种配置方式.


 

No 2 : 第二个我们还是回继续实现 ApplicationContextInitializer接口.

package com.yang.threadspringcase.initializer;

/*
 *@author:BaoYang
 *@Date: 2020/2/29
 *@description:
 */

import org.springframework.context.ApplicationContextInitializer;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.MapPropertySource;

import java.util.HashMap;
import java.util.Map;

public class SecondInitializer implements ApplicationContextInitializer<ConfigurableApplicationContext>
{

    @Override
    public void initialize(ConfigurableApplicationContext applicationContext)
    {
        ConfigurableEnvironment environment = applicationContext.getEnvironment();
        Map<String,Object> map = new HashMap<>();
        map.put("key2", "value2");
        MapPropertySource mapPropertySource = new MapPropertySource("secondInitializer", map);
        environment.getPropertySources().addLast(mapPropertySource);

        System.out.println("SecondInitializer Init Over");
    }
}

当然也需要指定一下, 这回指定类的地方,我们换一下,在application.properties中

在 application.properties中 

context.initializer.classes=com.yang.threadspringcase.initializer.SecondInitializer

使用这句来指定即可.


No 3 这里来第三种. 依然还是实现同样的接口

package com.yang.threadspringcase.initializer;

/*
 *@author:BaoYang
 *@Date: 2020/2/29
 *@description:
 */

import org.springframework.context.ApplicationContextInitializer;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.MapPropertySource;

import java.util.HashMap;
import java.util.Map;

public class ThreeInitializer implements ApplicationContextInitializer<ConfigurableApplicationContext>
{
    @Override
    public void initialize(ConfigurableApplicationContext applicationContext)
    {
        ConfigurableEnvironment environment = applicationContext.getEnvironment();
        Map<String,Object> map = new HashMap<>();
        map.put("key3", "value3");
        MapPropertySource mapPropertySource = new MapPropertySource("threeInitializer", map);
        environment.getPropertySources().addLast(mapPropertySource);

        System.out.println("ThreeInitializer Init Over");
    }
}

这回就直接加在代码里面来实现

SpringApplication springApplication = new SpringApplication(ThreadSpringCaseApplication.class);
springApplication.addInitializers(new ThreeInitializer());
ConfigurableApplicationContext context = springApplication.run(args);
        String key3 = context.getEnvironment().getProperty("key3");
        System.out.println(key3);

将启动的类修改为这样,第三种方式就可以了。


然后,我们启动一下项目就可以看到相应的效果了

 

然后就可以看到,三句胡乱打印的Log。细心的朋友就不难猜出,Initializer的加载顺序了,先从 application.properties中加载,再从META-INF/配置下加载 , 再从代码中add中加载.


我们再来debug看看.

直接将断点打在 SpringApplication ---> 314行, 如下的方法上

prepareContext(context, environment, listeners, applicationArguments, printedBanner);

然后debug启动,发现并没有打印 Initializer 中的内容

debug到 SpringApplication  621行 

applyInitializers(ConfigurableApplicationContext context)  --->  getInitializers()

这个就可以看到  initializers中已经有的Initialzers实现类信息,但是自信看下来,居然没有SecoedInitialzer的信息。然后debug一步一步的看.

当我们debug第一个  

DelegatingApplicationContextInitializer.initialize() --->  getInitializerClasses(environment)

这个方面从之前的环境加载之中加载从配置文件中配置的信息, 然后继续调用 SecondInitializer 中的 initialize方法

 

走完这个方法就可以看到控制输出  SecondInitializer Init Over 这句话

然后九个中的第一个走完,然后回一次走完剩下的八个.

这里分析完了,就可以看到SpringBoot源码再执行Initializer的实现类执行过程。然后跟我们的打印顺序一起关联起来就即可。


 

由于我目前很少使用 ApplicationContextInitializer 来加载东西,所以对于深入进去的内容并不是很了解。

目前了解的一般这样配置会在初始化Bean之前,加载好配置文件等信息功能。

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值