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 ...
随机推荐
- 关于mybatis-config.xml文件的基础解释
今天是我第一天落户博客园,想一想从mybatis框架开始写起吧.mybatis框架与Hibernate框架相比来说,专注于SQL语句,对SQL语句的要求比较高吧. 我觉得,对于mybatis框架来说, ...
- 只要三步!阿里云DLA帮你处理海量JSON数据
概述 您可能有大量应用程序产生的JSON数据,您可能需要对这些JSON数据进行整理,去除不想要的字段,或者只保留想要的字段,或者仅仅是进行数据查询. 那么,利用阿里云Data Lake Analyti ...
- ubuntn系统下将文件拷贝到优盘中及挂载概念理解
参考资料:http://jingyan.baidu.com/article/7082dc1c76f178e40a89bdd3.html: http://bbs.csdn.net/topics/3801 ...
- Django项目:CRM(客户关系管理系统)--39--31PerfectCRM实现King_admin编辑多对多限制
readonly_fields = ('qq', 'consultant','tags',) # 不可修改 # forms.py # ————————19PerfectCRM实现King_admin数 ...
- PHP获取搜索引擎关键词
有时候我们需要知道用户通过哪个搜索引擎,通过拿个关键词访问我们页面,当然js也可以实现,这里介绍下php的实现代码,包含(百度.谷歌.雅虎.搜狗.搜搜.必应.有道)几大搜索引擎的获取方法. //获取来 ...
- @at-root和#{&}结合
Sass有脚本模式#{},他和&不同之处是,&只用作选择器,它只能出现在一个复合的开始选择器,类似于一个类型选择器,如a或者h1.但#{}他表示的是一个插值,它可以用在任何地方.同样的 ...
- cmake how to create vs file filters
用cmakelists构建出来的工程,没有文件filters,可采用如下方法解决 set(SOURCE_LIST "lotteryTicket.cpp" "stdafx. ...
- day18 17.c3p0连接池使用
连接池时间长不用空闲着,dbcp是不回收的,性能可能有些问题.c3p0是可以自动回收.实际开发中c3p的生产力比dbcp强,性能上更强. package cn.itcast.datasource; i ...
- 【CodeVS】1023 GPA计算
1023 GPA计算 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 青铜 Bronze 题目描述 Description 小松终于步入了大学的殿堂,带着兴奋和憧憬,他参加了信息科学 ...
- Leetcode606.Construct String from Binary Tree根据二叉树创建字符串
你需要采用前序遍历的方式,将一个二叉树转换成一个由括号和整数组成的字符串. 空节点则用一对空括号 "()" 表示.而且你需要省略所有不影响字符串与原始二叉树之间的一对一映射关系的空 ...