启动一个SpringBoot的一个应用程序;它的入口就是:下面代码中的main方法;
1 2 3 4 5 6 7 | @SpringBootApplication public class SpringbootMybatisApplication {
public static void main(String[] args) { SpringApplication.run(SpringbootMybatisApplication.class, args); } } |
从入口代码中可以看出启动流程:
1. 创建SpringApplication对象:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | public SpringApplication(ResourceLoader resourceLoader, Class... primarySources) { // 定义启动需要的一些属性 this.sources = new LinkedHashSet(); this.bannerMode = Mode.CONSOLE; this.logStartupInfo = true; this.addCommandLineProperties = true; this.headless = true; this.registerShutdownHook = true; this.additionalProfiles = new HashSet(); this.resourceLoader = resourceLoader; Assert.notNull(primarySources, "PrimarySources must not be null"); this.primarySources = new LinkedHashSet(Arrays.asList(primarySources)); // 判断当前是否一个web应用 this.webApplicationType = this.deduceWebApplicationType(); // 从类路径下找到META‐INF/spring.factories配置的所有ApplicationContextInitializer;然后保存起来 this.setInitializers(this.getSpringFactoriesInstances(ApplicationContextInitializer.class)); // 从类路径下找到META‐INF/spring.factories配置的所有ApplicationListener this.setListeners(this.getSpringFactoriesInstances(ApplicationListener.class)); // 从多个配置类中找到有main方法的主配置类 this.mainApplicationClass = this.deduceMainApplicationClass(); } |
getSpringFactoriesInstances(clazz)就是在META‐INF/spring.factories配置的所有clazz对象
初始化配置了6个ApplicationContextInitializer和10个ApplicationListener
在对应的jar包下找到spring.factories,可以打开看一下spring-boot和spring-boot-autoconfigure中的spring.factories的文件
其中2个ApplicationContextInitializer和1个ApplicationListener
其中4个ApplicationContextInitializer和9个ApplicationListener
基本上配置ApplicationContextInitializer和ApplicationListener都在这两个文件中了,根据需要也可以自定义添加的。
2.运行Run方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 | public ConfigurableApplicationContext run(String... args) { StopWatch stopWatch = new StopWatch(); stopWatch.start(); ConfigurableApplicationContext context = null; Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList(); this.configureHeadlessProperty(); // 获取SpringApplicationRunListeners;从类路径下META‐INF/spring.factories SpringApplicationRunListeners listeners = this.getRunListeners(args); // 回调所有的获取SpringApplicationRunListener.starting()方法 listeners.starting();
Collection exceptionReporters; try { // 封装命令行参数 ApplicationArguments applicationArguments = new DefaultApplicationArguments(args); // 准备环境 创建环境完成后回调SpringApplicationRunListener.environmentPrepared();表示环境准备完成 ConfigurableEnvironment environment = this.prepareEnvironment(listeners, applicationArguments); this.configureIgnoreBeanInfo(environment); // 打印springboot标志 Banner printedBanner = this.printBanner(environment); // 创建ApplicationContext;决定创建web的ioc还是普通的ioc context = this.createApplicationContext(); exceptionReporters = this.getSpringFactoriesInstances(SpringBootExceptionReporter.class, new Class[]{ConfigurableApplicationContext.class}, new Object[]{context}); // 准备上下文环境; // 将environment保存到ioc中 context.setEnvironment(environment); // 调用applyInitializers()方法,回调之前保存在IOC容器中的所有的ApplicationContextInitialize的initialize方法 // 回调SpringApplicationRunListeners中的contextPrepared方法; listeners.contextPrepared(context); // 回调SpringApplicationRunListeners中的contextPrepared方法 listeners.contextLoaded(context); this.prepareContext(context, environment, listeners, applicationArguments, printedBanner); // 刷新容器; // 准备刷新;清理缓存 // 获取beanFactory this.postProcessBeanFactory(beanFactory); // this.invokeBeanFactoryPostProcessors(beanFactory); // this.registerBeanPostProcessors(beanFactory); // this.initMessageSource(); // this.initApplicationEventMulticaster(); // this.onRefresh(); // this.registerListeners(); // this.finishBeanFactoryInitialization(beanFactory); // this.finishRefresh(); // 扫描,创建,加载所有组件的地方;(配置类,组件,自动配置) this.refreshContext(context); //这里什么操作也没有做 this.afterRefresh(context, applicationArguments); stopWatch.stop(); if(this.logStartupInfo) { (new StartupInfoLogger(this.mainApplicationClass)).logStarted(this.getApplicationLog(), stopWatch); } // 回调SpringApplicationRunListeners的started方法 listeners.started(context); // 回调Runners // 从ioc容器中获取所有的ApplicationRunner和CommandLineRunner进行回调对应Runner的run方法 // 先回调ApplicationRunne,在回调CommandLineRunner // 这里标准环境没有runner 注册可以回调的 this.callRunners(context, applicationArguments); } catch (Throwable var10) { this.handleRunFailure(context, var10, exceptionReporters, listeners); throw new IllegalStateException(var10); }
try { // 回调SpringApplicationRunListeners的running方法 listeners.running(context); // 整个SpringBoot应用启动完成后返回启动的IOC容器 return context; } catch (Throwable var9) { this.handleRunFailure(context, var9, exceptionReporters, (SpringApplicationRunListeners)null); throw new IllegalStateException(var9); } } |
在SpringBoot中的比较重要的时间回调机制有:
ApplicationContextInitializer (配置在META-INF/spring.factories)
SpringApplicationRunListener (配置在META-INF/spring.factories)
ApplicationRunner (放在IOC容器中使用@Component的方式注入就可以了)
CommandLineRunner(放在IOC容器中使用@Component的方式注入就可以了)
注册自定义的ApplicationContextInitializer :
1 2 3 4 5 6 7 | public class NewApplicationContextInitializer implements ApplicationContextInitializer<ConfigurableApplicationContext>{
@Override public void initialize(ConfigurableApplicationContext configurableApplicationContext) { System.out.println("NewApplicationContextInitializer initialize..." + configurableApplicationContext); } } |
注册自定义的SpringApplicationRunListener :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 | public class NewSpringApplicationRunListener implements SpringApplicationRunListener{ /** * 创建构造器,如果不创建会报错 * @param springApplication * @param args */ public NewSpringApplicationRunListener(SpringApplication springApplication, String[] args){
} @Override public void starting() { System.out.println("1. NewSpringApplicationRunListener .... starting...."); }
@Override public void environmentPrepared(ConfigurableEnvironment configurableEnvironment) { System.out.println("2 NewSpringApplicationRunListener .... environmentPrepared...."); }
@Override public void contextPrepared(ConfigurableApplicationContext configurableApplicationContext) { System.out.println(" 3 NewSpringApplicationRunListener .... contextPrepared...."); }
@Override public void contextLoaded(ConfigurableApplicationContext configurableApplicationContext) { System.out.println("4 NewSpringApplicationRunListener .... contextLoaded...."); }
@Override public void started(ConfigurableApplicationContext configurableApplicationContext) { System.out.println(" 5 NewSpringApplicationRunListener .... started...."); }
@Override public void running(ConfigurableApplicationContext configurableApplicationContext) { System.out.println(" 6 NewSpringApplicationRunListener .... running...."); }
@Override public void failed(ConfigurableApplicationContext configurableApplicationContext, Throwable throwable) { System.out.println("NewSpringApplicationRunListener .... starting...."); } } |
注册自定义的ApplicationRunner:
1 2 3 4 5 6 7 8 | @Component public class NewApplicationRunner implements ApplicationRunner{
@Override public void run(ApplicationArguments applicationArguments) throws Exception { System.out.println("NewApplicationRunner..... run ...."); } } |
注册自定义的CommandLineRunner:
1 2 3 4 5 6 7 | @Component public class NewCommandLineRunner implements CommandLineRunner{ @Override public void run(String... strings) throws Exception { System.out.println("NewCommandLineRunner.... run ........"); } } |
对于ApplicationContextInitializer 和SpringApplicationRunListener 需要配置spring.factory文件,在resource目录下创建META-INF文件夹下面创建一个spring.factory文件将自定义的两个类注册进去;如下
在SpringBoot应用启动的时候就会按顺序调用对应类中的方法
留个问题:什么时候情况下回自定义这几种类型,希望以后学习中可以解决这个问题