创建应用

几个重要的事件回调机制  , 配置在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 启动配置原理【转】【补】的更多相关文章

  1. springboot启动配置原理之二(运行run方法)

    public ConfigurableApplicationContext run(String... args) { StopWatch stopWatch = new StopWatch(); s ...

  2. SpringBoot 启动配置原理

    几个重要的事件回调机制 ApplicationContextInitializer SpringApplicationRunListener ApplicationRunner CommandLine ...

  3. springboot启动配置原理之一(创建SpringApplication对象)

    几个重要的事件回调机制 配置在META-INF/spring.factories ApplicationContextInitializer SpringApplicationRunListener ...

  4. springboot启动配置原理之三(事件监听机制)

    ApplicationContextInitializer public class HelloApplicationContextInitializer implements Application ...

  5. SpringBoot启动过程原理

    最近这两年springboot突然火起来了,那么我们就来看看springboot的运行原理. 一.springboot的三种启动方式: 1.运行带有main方法的2.通过命令 Java -jar命令3 ...

  6. 这样讲 SpringBoot 自动配置原理,你应该能明白了吧

    https://juejin.im/post/5ce5effb6fb9a07f0b039a14 前言 小伙伴们是否想起曾经被 SSM 整合支配的恐惧?相信很多小伙伴都是有过这样的经历的,一大堆配置问题 ...

  7. 【SpringBoot1.x】SpringBoot1.x 启动配置原理 和 自定义starter

    SpringBoot1.x 启动配置原理 和 自定义starter 启动配置原理 本节源码 启动过程主要为: new SpringApplication(sources) 创建 SpringAppli ...

  8. springboot自动配置原理以及手动实现配置类

    springboot自动配置原理以及手动实现配置类 1.原理 spring有一个思想是"约定大于配置". 配置类自动配置可以帮助开发人员更加专注于业务逻辑开发,springboot ...

  9. SpringBoot自动配置原理

    前言 只有光头才能变强. 文本已收录至我的GitHub仓库,欢迎Star:https://github.com/ZhongFuCheng3y/3y 回顾前面Spring的文章(以学习的顺序排好): S ...

随机推荐

  1. Git同平台下多个账号配置

    在公司要使用公司和自己的两个账号都往GitHub上面提交,所以整理成笔记 具体配置项 StrictHostKeyChecking no UserKnownHostsFile /dev/null # 为 ...

  2. Django模型中的OneToOneField和ForeignKey有什么区别?

    说是ForeignKey是one-to-many的,并举了一个车的例子: 有两个配件表,一个是车轮表,另一个是引擎表.两个表都有一个car字段,表示该配件对应的车. 对于车轮来说,多个对应一个car的 ...

  3. LeetCode389Find the Difference找不同

    给定两个字符串 s 和 t,它们只包含小写字母. 字符串 t 由字符串 s 随机重排,然后在随机位置添加一个字母. 请找出在 t 中被添加的字母. 示例: 输入: s = "abcd&quo ...

  4. Django项目:CRM(客户关系管理系统)--41--33PerfectCRM实现King_admin编辑整张表限制

    readonly_table=False#默认表单不锁定 readonly_table=True#默认表单不锁定 # forms.py # ————————19PerfectCRM实现King_adm ...

  5. loj2544 「JXOI2018」游戏

    https://loj.ac/problem/2544 自己太傻,一遇到有关数学的题就懵逼,这种简单题竟然还得靠NicoDafaGood 在$[l,r]$这个区间内,如果没有数是$x$的因数,我们称$ ...

  6. opencv4 java 验证码噪点 8邻域降噪

    工程下载地址https://download.csdn.net/download/qq_16596909/11503962 程序运行后,同样会把图片存放在以下路径 首先来看一下原图 二值化后,可以把这 ...

  7. div style标签内嵌CSS样式

    我们在DIV标签内.SPAN标签内.p标签等html标签内使用style属性直接设置div的样式. 一.在<div>标签内使用style设置css样式   -   TOP 1.实例html ...

  8. linux文件系统配置文件

    文件系统 内核提供了一个接口,用来显示一些它的数据结构,这些数据结构对于决定诸如使用的中断.初始化的设备和内存统计信息之类的系统参数可能很有用.这个接口是作为一个独立但虚拟的文件系统提供的,称为 /p ...

  9. 创建动态MSSQL数据库表的方法

    代码如下: ImportsSystem.Data ImportsSystem.Data.SqlClient PublicClassForm1 InheritsSystem.windows.Forms. ...

  10. SourceTree windows免注册免登陆使用方法

    问题描述: 安装SourceTree后,首次使用时,需要登录账号:但我们在注册或登录时,可能根本无法打开网页,导致不能进入. 如下截图: 解决方法: 在目录C:\Users\XXXXX\AppData ...