一、@SpringBootApplication背后的秘密
@SpringBootApplication注解是以下三个注解的合体:@Configuration、@EnableAutoConfiguration、@ComponentScan
二、@Configuration
启动类上加了@Configuration注解后,启动类本身就是一个IOC容器配置类。
三、@EnableAutoConfiguration
@EnableAutoConfiguration注解是借助@Import的帮助,将所有符合自动配置条件的bean定义加载到IOC容器。
自动配置的幕后英雄:SpringFactoriesLoader
SpringFactoriesLoader属于spring框架私有的一种扩展方案,主要功能是从指定的配置文件META-INF/spring.factories加载配置。spring.factories文件是key=value格式,key和value都是完整的java类名。
对于@EnableAutoConfiguration来说,SpringFactoriesLoader提供了一种配置查找的功能支持,@EnableAutoConfiguration根据完整的类名作为key来查找,获取一组对应的@Configuration类。
@EnableAutoConfiguration自动配置的流程:从classpath中搜寻所有的META-INF/spring.Factories文件→将其中org.springframework.boot.autoconfigure.EnableAutoConfiguration对应的配置项通过java反射实例化为对应的标注了@Configuration的javaConfiguration形式的IOC配置类,然后汇总到一个并加载到IOC容器。
四、@ComponentScan
该注解可以自动扫描并加载符合条件的组件或bean的定义,最终将这些bean加载到容器中。
五、@SpringBootApplication:SpringBoot启动的一站式解决方案
在SpringBoot的启动类上加@SpringBootApplication注解就可以满足一般需求。
SpringBootApplication的执行流程:
1)创建一个SpringApplication对象实例,然后调用这个创建好的SpringApplication对象的run方法。在SpringApplication对象初始化前会提前做一下事情:
①:根据classpath里面是否存在某个特征类(org.springframework.web.context.ConfigurableWebApplicationContext)来决定是否应该创建一个为web应用使用的ApplicationContext类型,还是创建一个Standalone(单机、独立)应用使用的ApplicationContext类型。
②:使用SpringFactoriesLoader在应用的classpath中查找并加载所有可用的ApplicationContextInitializer。
③:使用SpringFactoriesLoader在应用的classpath中查找并加载所有可用的ApplicationListener。
④:推断并设置main方法的定义类
2)run方法刚开始执行时,首先遍历执行所有通过SpringFactoriesLoader可以查找到并加载的SpringApplicationRunListener,调用他们的started()方法,告诉SpringApplicationRunListener,springboot应用要开始启动了。
3)创建并配置当前springboot应用将要使用的Environment(包括配置要使用的PropertySource以及Profile)。
4)遍历调用所有SpringApplicationRunListener的environmentPrepared()方法,告诉他们当前springboot应用使用的Environment准备好了。
5)如果springApplication的showBanner属性被设置为true,则打印Banner.
6)根据用户是否明确设置了applicationContextClass类型以及初始化阶段的推断结果,决定该为当前Springboot应用创建什么类型的ApplicationContext并创建完成,然后根据条件决定是否添加ShutDownHook,决定是否使用自定义的BeanNameGenerator,决定是否使用自定义的ResourceLoader,当然,最终要的是将之前准备好的Environement设置给创建好的ApplicationContext使用。
7)ApplicationContext创建好之后,SpringApplication会再次借助SpringFactoriesLoader,查找并加载classpath中所有可用的ApplicationContextInitializer,然后遍历调用这些ApplicationContextInitializer的initializer方法来对已创建好的ApplicationContext进行进一步的处理。
8)遍历调用所有SpringApplicationRunListener的contextPrepared()方法,通知他们:SpringBoot应用使用的ApplicationContext准备好了。
9)将之前通过@EnableConfiguration获取的所有配置以及其他形式的IOC容器配置加载到已经准备完毕的ApplicationContext。
10)遍历调用所有的SpringApplicationRunListener的contextLoaded()方法,告知所有SpringApplicationRunListener,ApplicationContext装填完毕。
11)调用ApplicationContext的refresh()方法,完成IOC容器可用的最后一道工序。
12)查找当前ApplicationContext中是否注册有CommandLineRunner,如果有则遍历执行他们。
13)正常情况下,遍历执行SpringApplicationRunListener的finished()方法,告知他们“搞定“”(如果在执行过程中出现异常仍然会调用所有的SpringApplicationRunListener的finished()方法,只不过这种情况下会将异常信息一并传入处理)
至此一个完整的SpringBoot应用启动完毕!
六、SpringApplicationRunListener
SpringApplicationRunListener是一个只有Springboot应用的main方法执行过程中接收不同执行时点事件通知的监听者:
七、ApplicationListener
ApplicationListener属于Spring'框架对java中实现的监听者模式的一种框架实现,如果要为SpringBoot应用自定义ApplicationListener,有两种方法:
①:SpringApplication.addListeners(...)/SpringApplication.setListeners(...)方法添加一个或多个自定义的ApplicationListener
②:借助SpringFactoriesloader机制,在META-INF/spring.factories文件中添加配置
八、ApplicationContextInitializer
ApplicationContextInitializer主要目的是在ConfigurableApplicationContext的实例做进一步的设置或处理。
九、CommandLineRunner
1)执行时点是在SpringBoot启动类的main方法执行完成之前的最后一步。
2)SpringBoot应用的ApplicationContext中的任何CommandLineRunner,都会被加载执行。