spring-boot启动源码
1 运行SpringApplication.run()方法
--- org.springframework.boot.SpringApplication.SpringApplication(org.springframework.core.io.ResourceLoader, java.lang.Class<?>...)
2 确定应用程序类型
this.webApplicationType = WebApplicationType.deduceFromClasspath();
3 加载所有的初始化器
配置在spring-boot-autoconfigure 和 spring-boot 的spring.factories里
自定义初始化器:
a)实现 ApplicationContextInitializer接口 b)META-INF/spring.factories 配置文件
import org.springframework.context.ApplicationContextInitializer; import org.springframework.context.ConfigurableApplicationContext; /** * 初始化器 */ public class MyApplicationContextInitializer implements ApplicationContextInitializer<ConfigurableApplicationContext> { @Override public void initialize(ConfigurableApplicationContext configurableApplicationContext) { System.out.println("我是初始化的 MyApplicationContextInitializer..."); } }
配置
org.springframework.context.ApplicationContextInitializer=\ com.application.MyApplicationContextInitializer
4、加载所有的监听器
配置在spring-boot-autoconfigure 和 spring-boot 的spring.factories里
监听器加载的是实现了ApplicationListener 接口的类
5 设置运行的主类
--- org.springframework.boot.SpringApplication.run(java.lang.String...) public ConfigurableApplicationContext run(String... args) { //开启计时器 StopWatch stopWatch = new StopWatch(); stopWatch.start(); ConfigurableApplicationContext context = null; Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>(); configureHeadlessProperty(); //获取并启动监听器 SpringApplicationRunListeners listeners = getRunListeners(args); listeners.starting(); try { //设置应用程序参数,main方法里面执行静态run方法传入的参数 ApplicationArguments applicationArguments = new DefaultApplicationArguments( args); //准备环境变量,将maven和系统的环境变量都加载进来了 ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments); configureIgnoreBeanInfo(environment); Banner printedBanner = printBanner(environment); //反射创建应用程序上下文 context = createApplicationContext(); //*实例化异常报告器。自定义异常报告器:继承 SpringBootExceptionReporter 接口 //*1 开启异常报警器 exceptionReporters = getSpringFactoriesInstances( SpringBootExceptionReporter.class, new Class[] { ConfigurableApplicationContext.class }, context); //*2 以下代码中发生异常都会执行异常报警器 //准备上下文环境,为下一步刷新作准备:postProcessApplicationContext、applyInitializers、registerSingleton prepareContext(context, environment, listeners, applicationArguments, printedBanner); //刷新上下文,属于spring范畴,自动装配和启动tomcat refreshContext(context); //后置处理,留给用户扩展使用 afterRefresh(context, applicationArguments); //结束计时器 stopWatch.stop(); if (this.logStartupInfo) { new StartupInfoLogger(this.mainApplicationClass) .logStarted(getApplicationLog(), stopWatch); } //发布上下文准备就绪事件 listeners.started(context); //扩展功能,启动自定义的run方法 callRunners(context, applicationArguments); } catch (Throwable ex) { //3 捕获异常并调用异常报警器方法 handleRunFailure(context, ex, exceptionReporters, listeners); throw new IllegalStateException(ex); } try { listeners.running(context); } catch (Throwable ex) { handleRunFailure(context, ex, exceptionReporters, null); throw new IllegalStateException(ex); } return context; }
* 自定义异常报告器
配置在spring.factories里
监听器加载的是实现了 SpringBootExceptionReporter 接口的类
自定义异常报告器
import org.springframework.boot.SpringBootExceptionReporter; import org.springframework.context.ConfigurableApplicationContext; public class MyExceptionReporter implements SpringBootExceptionReporter { private ConfigurableApplicationContext context; // 必须要有一个有参的构造函数,否则启动会报错 MyExceptionReporter(ConfigurableApplicationContext context) { this.context = context; } @Override public boolean reportException(Throwable failure) { System.out.println("进入异常报告器"); failure.printStackTrace(); // 返回false会打印详细springboot错误信息,返回true则只打印异常信息 return false; } }
配置
org.springframework.boot.SpringBootExceptionReporter=\ com.baoyun.iyb.config.application.MyExceptionReporter
* 执行自定义的run方法
1。实现 ApplicationRunner 接口
2。实现 CommandLineRunner 接口
com.init.MyRunner
import org.springframework.boot.ApplicationArguments; import org.springframework.boot.ApplicationRunner; import org.springframework.boot.CommandLineRunner; public class MyRunner implements ApplicationRunner, CommandLineRunner { @Override public void run(ApplicationArguments args) throws Exception { System.out.println(" 我是自定义的run方法1,实现 ApplicationRunner 接口既可运行" ); } @Override public void run(String... args) throws Exception { System.out.println(" 我是自定义的run方法2,实现 CommandLineRunner 接口既可运行" ); } }