首先是`SpringApplication.run` 方法,方法拿到一个 `primary source` 然后解析加载配置(就是那个传进来的App.class)。 然后创建了个`SpringApplication`,创建的时候会检测这个是什么类型的项目,`this.webApplicationType = WebApplicationType.deduceFromClasspath();` ``` java public static ConfigurableApplicationContext run(Class[] primarySources, String[] args) { return new SpringApplication(primarySources).run(args); } ``` 把参数传进去,然后`run()`,根据项目类型创建`ConfigurableApplicationContext`, ``` java public ConfigurableApplicationContext run(String... args) { // 启动计时器 StopWatch stopWatch = new StopWatch(); stopWatch.start(); ConfigurableApplicationContext context = null; Collection exceptionReporters = new ArrayList<>(); configureHeadlessProperty(); // 这个东西用来管理多个listener,在创建的时候,从 META-INF/spring.factories拿到要创建的listener名字,创建实例 SpringApplicationRunListeners listeners = getRunListeners(args); // 启动listener listeners.starting(); try { ApplicationArguments applicationArguments = new DefaultApplicationArguments( args); // 创建运行参数 ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments); configureIgnoreBeanInfo(environment); // 输出开头那段Spring boot 什么什么的 Banner printedBanner = printBanner(environment); // 创建上下文 context = createApplicationContext(); // 异常报告 exceptionReporters = getSpringFactoriesInstances( SpringBootExceptionReporter.class, new Class[] { ConfigurableApplicationContext.class }, context); //前置上下文配置 prepareContext(context, environment, listeners, applicationArguments, printedBanner); // 刷新上下文 refreshContext(context); afterRefresh(context, applicationArguments); // 计时完毕 stopWatch.stop(); if (this.logStartupInfo) { new StartupInfoLogger(this.mainApplicationClass) .logStarted(getApplicationLog(), stopWatch); } listeners.started(context); callRunners(context, applicationArguments); } catch (Throwable ex) { 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; } ``` listeners 是拿到这些名字来创建东西的: ``` java # Application Listeners org.springframework.context.ApplicationListener=\ org.springframework.boot.ClearCachesApplicationListener,\ org.springframework.boot.builder.ParentContextCloserApplicationListener,\ org.springframework.boot.context.FileEncodingApplicationListener,\ org.springframework.boot.context.config.AnsiOutputApplicationListener,\ org.springframework.boot.context.config.ConfigFileApplicationListener,\ org.springframework.boot.context.config.DelegatingApplicationListener,\ org.springframework.boot.context.logging.ClasspathLoggingApplicationListener,\ org.springframework.boot.context.logging.LoggingApplicationListener,\ org.springframework.boot.liquibase.LiquibaseServiceLocatorApplicationListener ``` 也就是说,我们是可以自定义Listener然后,监听相应的Event 只要实现`ApplicationListener` ``` java /** * @author dqn * created at 2019/2/10 19:20 */ public class MyListener implements ApplicationListener { @Override public void onApplicationEvent(ApplicationEvent event) { // 监听ApplicationStartingEvent if (event instanceof ApplicationStartedEvent) { System.out.println("ApplicationStartedEvent listened"); } // 监听ApplicationEnvironmentPreparedEvent else if (event instanceof ApplicationEnvironmentPreparedEvent) { System.out.println("ApplicationEnvironmentPreparedEvent listened"); } // 监听ApplicationPreparedEvent else if (event instanceof ApplicationPreparedEvent) { System.out.println("ApplicationPreparedEvent listened"); } // 监听ApplicationReadyEvent else if (event instanceof ApplicationReadyEvent) { System.out.println("ApplicationReadyEvent listened"); } // 监听ApplicationFailedEvent else if (event instanceof ApplicationFailedEvent) { System.out.println("ApplicationFailedEvent listened"); } } } ``` 在`META-INF/spring.factories`加上 ``` org.springframework.context.ApplicationListener=\ me.dqn.listener.MyListener ``` 即可。当然也可以手动添加: ``` java public static void main(String[] args) { SpringApplication application = new SpringApplication(App.class); application.addListeners(new MyListener()); application.run(args); } ```