work hard work smart

专注于Java后端开发。 不断总结,举一反三。
  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

Spring Boot 系统初始化器

Posted on 2020-02-06 14:08  work hard work smart  阅读(1211)  评论(1编辑  收藏  举报

1、Spring Boot 系统初始化器

系统初始化器介绍

SpringFactoriesLoader介绍

系统初始化器原理

 

2、系统初始化器介绍

类名: ApplicationContextinitializer

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

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

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

 

 

3、系统初始化器实践

创建系统初始化器方式一(实现原理:定义在spring.factories 文件中被SpringFactoriesLoader发现注册)

1)创建初始化器

在包initializer下创建FirstInitializer

/**
 *
 * 第一个系统初始化器
 */
@Order(1)
public class FirstInitializer  implements ApplicationContextInitializer<ConfigurableApplicationContext> {
    @Override
    public void initialize(ConfigurableApplicationContext applicationContext) {
        ConfigurableEnvironment environment = applicationContext.getEnvironment();
        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");
    }
}

  

2) 创建spring.factories 

 

 

内容为:

org.springframework.context.ApplicationContextInitializer=com.example.demo.initialize.FirstInitializer


3) 创建服务类 TestService 
@Component
public class TestService implements ApplicationContextAware
{

    private ApplicationContext applicationContext;



    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }

    public String test(){
        return  applicationContext.getEnvironment().getProperty("key1");
    }
}

  

4) 在Controller层增加方法

    @RequestMapping("/test")
    @ResponseBody
    public String test(){
        return  testService.test();
    }

  

5) 启动工程查看效果

可以发现打印了run FirstInitializer

 

 然后调用接口。返回值为之前设置的value1

 

 

创建系统初始化器方式二(实现原理:初始化完毕手动添加)

1)订单创建初始化器

@Order(2)
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("run SecondInitializer");
    }
}

  

2) SB2Application改成如下

@SpringBootApplication
@MapperScan("com.example.demo.mapper")
public class Sb2Application {

	public static void main(String[] args) {
		//SpringApplication.run(Sb2Application.class, args);
		SpringApplication springApplication = new SpringApplication(Sb2Application.class);
		springApplication.addInitializers(new SecondInitializer());
		springApplication.run(args);
	}

}

  

3) 修改Service的test方法

   public String test(){
        return  applicationContext.getEnvironment().getProperty("key2");
    }

 

4)启动(说明两个初始化器都已经创建)

. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v2.1.6.RELEASE)

run FirstInitializer
run SecondInitializer

 

5)、测试返回结果。返回value2

 

 

创建系统初始化器方式三(实现原理:定义成环境变量被DelegatingApplicationContextInitializer发现注册)

1)创建初始化器

@Order(3)
public class ThirdInitializer 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("thirdInitializer", map);
        environment.getPropertySources().addLast(mapPropertySource);
        System.out.println("run ThirdInitializer");
    }
}

  

2) 在application.properties 增加

context.initializer.classes=com.example.demo.initializer.ThirdInitializer

 

 

3)、修改TestServer的test方法

    public String test(){
        return  applicationContext.getEnvironment().getProperty("key3");
    }

  

4) 启动测试

 

 可以发现打印的顺序和定义的不一致。第三个ThirdInitializer初始化器优先于第一个和第二个打印出来。

 

使用接口测试,返回value2

 

那springboot初始化器是如何被识别呢,靠的就是SpringFactoriesLoader

springboot初始化器原理: 

初始化SpringApplication  工厂加载机制 SpringFactoriesLoader

 调用run方法: Spring Boot 系统初始化器是如何被调用的,以及实现原理