创建应用
几个重要的事件回调机制 , 配置在META-INF/spring.factories
ApplicationContextInitializer
SpringApplicationRunListener
只需要放在ioc容器中
ApplicationRunner
CommandLineRunner
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被加载
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-INFspring.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注解