几个重要的事件回调机制
- 配置在META-INF/spring.factories
ApplicationContextInitializer
SpringApplicationRunListener
- 只需要放在ioc容器中
ApplicationRunner
CommandLineRunner
启动流程:
1、创建SpringApplication对象
SpringApplication.class
public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
this.sources = new LinkedHashSet();
this.bannerMode = Mode.CONSOLE;
this.logStartupInfo = true;
this.addCommandLineProperties = true;
this.addConversionService = true;
this.headless = true;
this.registerShutdownHook = true;
this.additionalProfiles = new HashSet();
this.isCustomEnvironment = false;
this.lazyInitialization = false;
this.resourceLoader = resourceLoader;
Assert.notNull(primarySources, "PrimarySources must not be null");
//保存主配置类
this.primarySources = new LinkedHashSet(Arrays.asList(primarySources));
/判断当前是否一个web应用
this.webApplicationType = WebApplicationType.deduceFromClasspath();
//从类路径下找到META-INF/spring.factories配置的所有ApplicationContextInitializer;然后保存起来
this.setInitializers(this.getSpringFactoriesInstances(ApplicationContextInitializer.class));
//从类路径下找到ETA-INF/spring.factories配置的所有ApplicationListener
this.setListeners(this.getSpringFactoriesInstances(ApplicationListener.class));
//从多个配置类中找到有main方法的主配置类
this.mainApplicationClass = this.deduceMainApplicationClass();
}
2、运行run方法
public ConfigurableApplicationContext run(String... args) {
StopWatch stopWatch = new StopWatch();
stopWatch.start();
//声明IOC容器
ConfigurableApplicationContext context = null;
Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList();
//awt
this.configureHeadlessProperty();
//获取SpringApplicationRunListeners;从类路径下META-INF/spring.factories
SpringApplicationRunListeners listeners = this.getRunListeners(args);
//回调所有的获取SpringApplicationRunListener.starting()方法
listeners.starting();
Collection exceptionReporters;
try {
//封装命令行参数
ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
//准备环境
ConfigurableEnvironment environment = this.prepareEnvironment(listeners, applicationArguments);
//创建环境完成后回调SpringApplicationRunListener.environmentPrepared();表示环境准备完成
this.configureIgnoreBeanInfo(environment);
//打印banner图标
Banner printedBanner = this.printBanner(environment);
//创建ApplicationContext;决定创建web的ioc还是普通的ioc
context = this.createApplicationContext();
//做异常分析报告
exceptionReporters = this.getSpringFactoriesInstances(SpringBootExceptionReporter.class, new Class[]{ConfigurableApplicationContext.class}, context);
//准备上下文环境;将environment保存到ioc中;而且执行applyInitializers();
//applyInitializers():回调之前保存的所有的ApplicationContextInitializer的initialize方法
//回调所有的SpringApplicationRunListener的contextPrepared()
this.prepareContext(context, environment, listeners, applicationArguments, printedBanner);
//prepareContext运行完成以后回调所有的SpringApplicationRunListener的contextLoaded();
//刷新容器;ioc容器初始化(如果是web应用还会创建嵌入式的Tomcat);Spring注解版
//扫描,创建,加载所有组件的地方;(配置类,组件,自动配置)
this.refreshContext(context);
//从ioc容器中获取所有的ApplicationRunner和CommandLineRunner进行回调
//ApplicationRunner先回调,CommandLineRunner再回调
this.afterRefresh(context, applicationArguments);
stopWatch.stop();
if (this.logStartupInfo) {
(new StartupInfoLogger(this.mainApplicationClass)).logStarted(this.getApplicationLog(), stopWatch);
}
//回调所有的SpringApplicationRunListener的started()
listeners.started(context);
this.callRunners(context, applicationArguments);
} catch (Throwable var10) {
this.handleRunFailure(context, var10, exceptionReporters, listeners);
throw new IllegalStateException(var10);
}
try {
//所有的SpringApplicationRunListener回调running方法
listeners.running(context);
//整个SpringBoot应用启动完成以后返回启动的ioc容器;
return context;
} catch (Throwable var9) {
this.handleRunFailure(context, var9, exceptionReporters, (SpringApplicationRunListeners)null);
throw new IllegalStateException(var9);
}
}
总结:
创建SpringApplication对象
保存主配置类
判断当前是否时一个web应用
从类路径下找到 META-INFO/spring.factories 配置的所有 ApplicationContextInitialize;
类路径下找到 META-INFO/spring.factories 配置的所有 ApplicationListener
从多个配置类中找到有main方法的主配置类
运行 run 方法
- 声明IOC容器
- 从类路径下 META-INFO/spring.factories 获取 SpringApplicationRunListeners
- 回调所有获取的 SpringApplicationRunListener.starting() 方法
- 封装命令行参数
- 准备环境;创建环境后完成回调 SpringApplicationRunListener.environmentPrepared(); 表示环境准备完成 (in wai le meng ci pei er)
- 打印 banner 图标
- 创建 ApplicationContext;决定创建 web 的 ioc 还是普通的 ioc
- 做异常分析报告
- 准备上下文环境,将 environment 保存到 ioc 中;而且执行 applyInitializers()【应用初始化】; 回调之前保存的所有 ApplicationContextInitializer 的 Initialize 方法;回调所有的 SpringApplicationRunListener 的 contextPrepared();prepareContext 运行完成后回调所有 SpringApplicationRunListener 的 contextLoaded()
- 刷新容器;ioc 容器初始化(如果是web应用还会创建嵌入式的Tomcat);扫描,创建,加载所有组件的地方;
- 从ioc容器中获取所有的ApplicationRunner和CommandLineRunner进行回调;ApplicationRunner先回调,CommandLineRunner再回调
- 所有的 SpringApplicationRunListener回调 finished 方法
- 整个 SpringBoot应用启动完成以后返回启动的 ioc 容器;
3、事件监听机制
配置在META-INF/spring.factories
ApplicationContextInitializer
public class HelloApplicationContextInitializer implements ApplicationContextInitializer<ConfigurableApplicationContext> {
@Override
public void initialize(ConfigurableApplicationContext applicationContext) {
System.out.println("ApplicationContextInitializer...initialize..."+applicationContext);
}
}
SpringApplicationRunListener
package com.akieay.akieayblog.admin.listener;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.SpringApplicationRunListener;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.core.env.ConfigurableEnvironment;
/**
* @author admin
*/
public class HelloSpringApplicationRunListener implements SpringApplicationRunListener {
//必须有的构造器
public HelloSpringApplicationRunListener(SpringApplication application, String[] args){
}
@Override
public void starting() {
System.out.println("SpringApplicationRunListener...starting...");
}
@Override
public void environmentPrepared(ConfigurableEnvironment environment) {
Object o = environment.getSystemProperties().get("os.name");
System.out.println("SpringApplicationRunListener...environmentPrepared.."+o);
}
@Override
public void contextPrepared(ConfigurableApplicationContext context) {
System.out.println("SpringApplicationRunListener...contextPrepared...");
}
@Override
public void contextLoaded(ConfigurableApplicationContext context) {
System.out.println("SpringApplicationRunListener...contextLoaded...");
}
@Override
public void started(ConfigurableApplicationContext context) {
System.out.println("SpringApplicationRunListener...started...");
}
@Override
public void running(ConfigurableApplicationContext context) {
System.out.println("SpringApplicationRunListener...running...");
}
@Override
public void failed(ConfigurableApplicationContext context, Throwable exception) {
System.out.println("SpringApplicationRunListener...failed...");
}
}
配置(META-INF/spring.factories)
org.springframework.context.ApplicationContextInitializer=\
com.akieay.akieayblog.admin.listener.HelloApplicationContextInitializer
org.springframework.boot.SpringApplicationRunListener=\
com.akieay.akieayblog.admin.listener.HelloSpringApplicationRunListener
只需要放在ioc容器中
ApplicationRunner
@Component
public class HelloApplicationRunner implements ApplicationRunner {
@Override
public void run(ApplicationArguments args) throws Exception {
System.out.println("ApplicationRunner...run....");
}
}
CommandLineRunner
@Component
public class HelloCommandLineRunner implements CommandLineRunner {
@Override
public void run(String... args) throws Exception {
System.out.println("CommandLineRunner...run..."+ Arrays.asList(args));
}
}