创建应用

几个重要的事件回调机制  , 配置在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. JasperReport生命周期3

    JasperReports的主要目的是为了在一个简单而灵活的方式创建页面为导向,准备好打印文档.下面的流程图描述了一个典型的工作流程,同时创建报表. 如在图片的生命周期具有以下明显的阶段 设计报表在这 ...

  2. GYM100633J. Ceizenpok’s formula 扩展lucas模板

    J. Ceizenpok’s formula time limit per test 2.0 s memory limit per test 256 MB input standard input o ...

  3. LA3029 City Game

    Bob is a strategy game programming specialist. In his new city building game the gaming environment ...

  4. 未加星标 Linux磁盘下查看I/O磁盘的性能

    iostat查看linux硬盘IO性能 rrqm/s:每秒进行merge的读操作数目.即delta(rmerge)/s wrqm/s:每秒进行merge的写操作数目.即delta(wmerge)/s ...

  5. ssh实现免密码登录和文件传输

    一般的用户名密码认证不安全,很容易被暴力破解,还不方便:而大多数人都是选择使用 SSH 密钥认证,不仅安全还不用每次输密码 ssh密钥对 # 使用 ssh-keygen 生成非对称密钥,一路回车即可 ...

  6. JavaScript内容梳理 示例之模态对话框 示例之全选和反选以及取消 示例之后台管理左侧菜单

    <!DOCTYPE html> <!--示例之模态对话框--> <html lang="en"> <head> <meta c ...

  7. H5C3--过渡transition

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  8. 关于JavaScript的43道题①

    最近在github上大火的43到js代码题,有很多人搬运.原链接https://github.com/lydiahallie/javascript-questions 1.下面代码的输出是什么? fu ...

  9. mysql 导入txt数据

    在导入数据的时候,特别是数据包含中文的时候,在导入的时候,容易出现编码规则引起的错误.例如错误提示:Invalid utf8 character string: '' 这种情况下,我们可以把需要导入的 ...

  10. POJ1991 NOI1999棋盘分割

    棋盘分割 Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 15581   Accepted: 5534 Description ...