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 ...
随机推荐
- Eureka Instance实例信息配置
Eureka包含四个部分的配置 instance:当前Eureka Instance实例信息配置 client:Eureka Client客户端特性配置 server:Eureka Server注册中 ...
- 【One by one系列】一步步开始使用Redis吧(一)
One by one,一步步开始使用Redis吧(一) 最近有需求需要使用redis,之前也是随便用用,从来也没有归纳总结,今天想睡觉,但是又睡不着,外面阳光不错,气温回升了,2019年6月1日,成都 ...
- storm-jdbc的使用
最近项目组分配到研究storm-jdbc用法 发现网上关于insert和query方法挺多的,但是自定义方法很少.而且用法上也挺多缺陷.在此自己总结记录一下 JdbcInsertBolt 的核心代码 ...
- JavaBean基础学习总结
学习目标: 掌握JavaBean的基本定义格式. 掌握Web目录的标准结构. 掌握JSP中对JavaBean支持的三个标签,即<jsp:useBean>,<jsp:setProper ...
- Docker(五)安装Fastdfs
https://blog.csdn.net/qq_37759106/article/details/82981023 有2个提示: 这篇博客nginx开放的80端口, 首先要打开防火墙80的端口: 测 ...
- 用Python的requests库作接口测试——对响应进行迭代
使用 requests.Response.iter_lines() 方法,可以很方便地对流式API(例如 Twitter的流式API )的响应进行迭代. 简单地设置 stream 为 True 便可以 ...
- php5.3中namespace的说明,帮助初次接触namespace的phper快速理解
命名空间一个最明确的目的就是解决重名问题,PHP中不允许两个函数或者类出现相同的名字,否则会产生一个致命的错误.这种情况下只要避免命名重复就可以解决,最常见的一种做法是约定一个前缀,但是方法名变的很长 ...
- 前端小知识--区分get和post请求
get和post是HTTP协议中的两种发送请求的方法. 如果你还不了解http,可以点击[HTTP协议①介绍](https://www.jianshu.com/p/632b890b75ac)[HTTP ...
- SpringBoot+Shiro+mybatis整合实战
SpringBoot+Shiro+mybatis整合 1. 使用Springboot版本2.0.4 与shiro的版本 引入springboot和shiro依赖 <?xml version=&q ...
- spring cloud深入学习(五)-----熔断器Hystrix
雪崩效应 在微服务架构中通常会有多个服务层调用,基础服务的故障可能会导致级联故障,进而造成整个系统不可用的情况,这种现象被称为服务雪崩效应.服务雪崩效应是一种因“服务提供者”的不可用导致“服务消费者” ...