springboot 启动配置原理【转】【补】
创建应用
几个重要的事件回调机制 , 配置在META-INF/spring.factories
ApplicationContextInitializer
SpringApplicationRunListener
只需要放在ioc容器中
ApplicationRunner
CommandLineRunner
一、创建SpringApplication对象
private void initialize(Object[] sources) {
//保存主配置类
if (sources != null && sources.length > 0) {
this.sources.addAll(Arrays.asList(sources));
}
//判断当前是否一个web应用
this.webEnvironment = deduceWebEnvironment();
//从类路径下找到META-INF/spring.factories配置的所有ApplicationContextInitializer;然后保存起来 ,
//比如spring-boot-autoconfigure-1.5.14.RELEASE.jar包的类路径下的/META-INF/spring.factories就有org.springframework.context.ApplicationContextInitializer=xxx,xxx
setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
//从类路径下找到META-INF/spring.factories配置的所有ApplicationListener,
//比如spring-boot-autoconfigure-1.5.14.RELEASE.jar包的类路径下的/META-INF/spring.factories就有org.springframework.context.ApplicationListener=xxx,xxx
setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
//从多个配置类中找到有main方法的主配置类
this.mainApplicationClass = deduceMainApplicationClass();
}
ApplicationContextInitializer.class一开始有以下几个类从/META-INF/spring.factories被加载

ApplicationListener.class一开始有以下几个类从/META-INF/spring.factories被加载

二、运行run方法
new SpringApplication(sources).run(args)
public ConfigurableApplicationContext run(String... args) {
StopWatch stopWatch = new StopWatch();
stopWatch.start();
ConfigurableApplicationContext context = null;
FailureAnalyzers analyzers = null;
configureHeadlessProperty();
//从类路径下找到META-INF/spring.factories配置的所有SpringApplicationRunListeners,
//比如spring-boot-autoconfigure-1.5.14.RELEASE.jar包的类路径下的/META-INF/spring.factories就有org.springframework.context.SpringApplicationRunListeners=xxx,xxx
SpringApplicationRunListeners listeners = getRunListeners(args);//内部方法是 getSpringFactoriesInstances(SpringApplicationRunListener.class, types, this, args)
//回调所有的获取SpringApplicationRunListener.starting()方法
listeners.starting();
try {
//封装命令行参数
ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
//准备环境, 配置profile,logger,peroertySources等等
ConfigurableEnvironment environment = prepareEnvironment(listeners,applicationArguments);
//创建环境完成后回调SpringApplicationRunListener.environmentPrepared();表示环境准备完成
//日志中打印springBoot的Banner(log)
Banner printedBanner = printBanner(environment);
//创建ApplicationContext;决定创建web的ioc还是普通的ioc ,方法内部使用BeanUtils.instantiate(contextClass)反射来创建
context = createApplicationContext();
//出现异常后, 在本方法最后做异常分析报告用的
analyzers = new FailureAnalyzers(context);
prepareContext(context, environment, listeners, applicationArguments,printedBanner);
///{
//context.setEnvironment(environment); 准备上下文环境;将environment保存到ioc即context中
//applyInitializers(context); 回调之前保存的所有的ApplicationContextInitializer的initialize()方法
//listeners.contextPrepared(context); 回调所有的SpringApplicationRunListener的contextPrepared();
//context.getBeanFactory().registerSingleton("springApplicationArguments",applicationArguments); 注册命令行参数对象
//listeners.contextLoaded(context); 回调所有的SpringApplicationRunListener的contextLoaded(),表示环境准备好了
//}
//刷新容器;ioc容器初始化(如果是web应用还会创建嵌入式的Tomcat);Spring注解版中有说明
//扫描,创建,加载所有组件,包括自动(配置)类,@Bean组件等等
refreshContext(context);
//{....
//finishBeanFactoryInitialization(beanFactory); //初始化所有非延迟加载的单实例bean
//...}
//从ioc容器中获取所有的ApplicationRunner和CommandLineRunner进行回调
//ApplicationRunner先回调,CommandLineRunner再回调
afterRefresh(context, applicationArguments);
//所有的SpringApplicationRunListener回调finished方法
listeners.finished(context, null);
stopWatch.stop();
if (this.logStartupInfo) {
new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), stopWatch);
}
//整个SpringBoot应用启动完成以后返回启动的ioc容器;
return context;
}
catch (Throwable ex) {
handleRunFailure(context, listeners, analyzers, ex);
throw new IllegalStateException(ex);
}
}
3、自定义事件监听器
配置在META-INF/spring.factories
ApplicationContextInitializer
ApplicationContextInitializer本身是个接口, 里面的泛型C用于监听ConfigurableApplicationContext
public interface ApplicationContextInitializer<C extends ConfigurableApplicationContext> {
void initialize(C var1);
}
public class MyApplicationContextInitializer implements ApplicationContextInitializer<ConfigurableApplicationContext> {
@Override
public void initialize(ConfigurableApplicationContext applicationContext) {
System.err.println("MyApplicationContextInitializer " + applicationContext);
}
}
SpringApplicationRunListener
必须有的构造器 , 不然会无法初始该类型的监听器
public class MySpringApplicationRunListener implements SpringApplicationRunListener {
/**
* 必须有的构造器 , 不然会无法初始该类型的监听器
*/
public MySpringApplicationRunListener(SpringApplication application, String[] args){
}
@Override
public void starting() {
System.err.println("MySpringApplicationRunListener starting");
}
@Override
public void environmentPrepared(ConfigurableEnvironment environment) {
//可以获取环境变量
Object os_name = environment.getSystemProperties().get("os.name");
System.err.println("MySpringApplicationRunListener environmentPrepared , os_name : "+ os_name);
}
@Override
public void contextPrepared(ConfigurableApplicationContext context) {
System.err.println("MySpringApplicationRunListener contextPrepared");
}
@Override
public void contextLoaded(ConfigurableApplicationContext context) {
System.err.println("MySpringApplicationRunListener contextLoaded");
}
@Override
public void finished(ConfigurableApplicationContext context, Throwable exception) {
System.err.println("MySpringApplicationRunListener finished");
}
}
注意:ApplicationContextInitializer , SpringApplicationRunListener 都需要配置在(META-INF/spring.factories)
#具体可参考该文件配置 spring-boot-autoconfigure-1.5.14.RELEASE.jar!\META-INF\spring.factories #initializer , \代表换行衔接下一行;,分隔多个class类
org.springframework.context.ApplicationContextInitializer=\
com.example.demo.config.listener.MyApplicationContextInitializer #listener
org.springframework.context.SpringApplicationRunListener=\
com.example.demo.config.listener.MySpringApplicationRunListener
ApplicationRunner
@Component
public class MyApplicationRunner implements ApplicationRunner {
@Override
public void run(ApplicationArguments args) throws Exception {
System.out.println("ApplicationRunner...run...."+ Arrays.asList(args));
}
}
CommandLineRunner
@Component
public class MyCommandLineRunner implements CommandLineRunner {
@Override
public void run(String... args) throws Exception {
System.out.println("CommandLineRunner...run..."+ Arrays.asList(args));
}
}
注意: ApplicationRunner , CommandLineRunner 只需要放在ioc容器中 , 即使用@Component注解
自定义Starter
springboot 启动配置原理【转】【补】的更多相关文章
- springboot启动配置原理之二(运行run方法)
public ConfigurableApplicationContext run(String... args) { StopWatch stopWatch = new StopWatch(); s ...
- SpringBoot 启动配置原理
几个重要的事件回调机制 ApplicationContextInitializer SpringApplicationRunListener ApplicationRunner CommandLine ...
- springboot启动配置原理之一(创建SpringApplication对象)
几个重要的事件回调机制 配置在META-INF/spring.factories ApplicationContextInitializer SpringApplicationRunListener ...
- springboot启动配置原理之三(事件监听机制)
ApplicationContextInitializer public class HelloApplicationContextInitializer implements Application ...
- SpringBoot启动过程原理
最近这两年springboot突然火起来了,那么我们就来看看springboot的运行原理. 一.springboot的三种启动方式: 1.运行带有main方法的2.通过命令 Java -jar命令3 ...
- 这样讲 SpringBoot 自动配置原理,你应该能明白了吧
https://juejin.im/post/5ce5effb6fb9a07f0b039a14 前言 小伙伴们是否想起曾经被 SSM 整合支配的恐惧?相信很多小伙伴都是有过这样的经历的,一大堆配置问题 ...
- 【SpringBoot1.x】SpringBoot1.x 启动配置原理 和 自定义starter
SpringBoot1.x 启动配置原理 和 自定义starter 启动配置原理 本节源码 启动过程主要为: new SpringApplication(sources) 创建 SpringAppli ...
- springboot自动配置原理以及手动实现配置类
springboot自动配置原理以及手动实现配置类 1.原理 spring有一个思想是"约定大于配置". 配置类自动配置可以帮助开发人员更加专注于业务逻辑开发,springboot ...
- SpringBoot自动配置原理
前言 只有光头才能变强. 文本已收录至我的GitHub仓库,欢迎Star:https://github.com/ZhongFuCheng3y/3y 回顾前面Spring的文章(以学习的顺序排好): S ...
随机推荐
- Http请求中的Content-Type
转载至:https://segmentfault.com/a/1190000013056786?utm_source=tag-newest 一 前言 ----现在搞前端的不学好http有关的知识已经不 ...
- OCP/OCA Oracle 学习001
select * from TEST3 t select object_type, count(object_type) from user_objects group by object_type ...
- Nginx与PHP工作原理
Nginx的工作原理 1.Nginx的模块与工作原理 Nginx由内核和模块组成,其中,内核的设计非常微小和简洁,完成的工作也非常简单,仅仅通过查找配置文件将客户端请求映射到一个location bl ...
- CentOS 6 忘记root密码的修改方法
1.Linux的root密码修改不像Windows的密码修改找回,Windows的登录密码忘记需要介入工具进行解决.CentOS6和CentOS7的密码方法也是不一样的,具体如下: 2.centos ...
- 2019-8-31-dotnet-如何调试某个文件是哪个代码创建
title author date CreateTime categories dotnet 如何调试某个文件是哪个代码创建 lindexi 2019-08-31 16:55:58 +0800 201 ...
- 部分树形DP的优化
ural1018. Binary Apple Tree 题目大意 有一棵n个节点的树,树上每个节点有一个值,选择m个节点使这些节点值的和最大 要求:如果选当前节点,则必须选它的父节点 解法: 我们设d ...
- spring源码学习之容器的扩展(二)
六 BeanFactory的后处理BeanFactory作为spring容器的基础,用于存放所有已经加载的bean,为了保证程序上的高扩展性,spring针对BeanFactory做了大量的扩展,比如 ...
- TZ_09_MyBatis的pageHelper
1.分页操作使用MyBatis的PageHelper 1>导入pageHelper的坐标 <dependency> <groupId>com.github.pagehel ...
- PHP--年龄转生日、生日转年龄
/** * 年龄转生日(模糊结果) * @parameter int age(年龄) * @parameter string symbol(分隔符) * @return string (yyyy*mm ...
- Leetcode628.Maximum Product of Three Numbers三个数的最大乘积
给定一个整型数组,在数组中找出由三个数组成的最大乘积,并输出这个乘积. 示例 1: 输入: [1,2,3] 输出: 6 示例 2: 输入: [1,2,3,4] 输出: 24 注意: 给定的整型数组长度 ...