本文章基于springboot2.1.1
目录
1 启动
@SpringBootApplication
@ServletComponentScan
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
public static ConfigurableApplicationContext run(Class<?> primarySource,
String... args) {
return run(new Class<?>[] { primarySource }, args);
}
public static ConfigurableApplicationContext run(Class<?>[] primarySources,
String[] args) {
return new SpringApplication(primarySources).run(args);
}
public SpringApplication(Class<?>... primarySources) {
this(null, primarySources);
}
2 SpringApplication的构造
public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
this.resourceLoader = resourceLoader;
Assert.notNull(primarySources, "PrimarySources must not be null");
//将primarySources即我们自己写的启动类放入set中
this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
//从类路径中判断应用程序类型
this.webApplicationType = WebApplicationType.deduceFromClasspath();
//由接口获取其实现类的对象实例
//从META-INF/spring.factories文件中获取ApplicationContextInitializer接口的实现类
//利用反射创建所有实现类的对象存放到变量initializers,List集合中
setInitializers((Collection) getSpringFactoriesInstances(
ApplicationContextInitializer.class));
//同上
setListeners((Collection) getSpringFactoriesInstances(
ApplicationListener.class));
//通过获取当前调用栈,找到main方法所在的类,即为启动类
this.mainApplicationClass = deduceMainApplicationClass();
}
当前栈中储存了正在运行的方法的方法信息
2.1 从类路径中判断应用程序类型
private static final String[] SERVLET_INDICATOR_CLASSES = { "javax.servlet.Servlet",
"org.springframework.web.context.ConfigurableWebApplicationContext" };
private static final String WEBMVC_INDICATOR_CLASS = "org.springframework."
+ "web.servlet.DispatcherServlet";
private static final String WEBFLUX_INDICATOR_CLASS = "org."
+ "springframework.web.reactive.DispatcherHandler";
private static final String JERSEY_INDICATOR_CLASS = "org.glassfish.jersey.servlet.ServletContainer";
private static final String SERVLET_APPLICATION_CONTEXT_CLASS = "org.springframework.web.context.WebApplicationContext";
private static final String REACTIVE_APPLICATION_CONTEXT_CLASS = "org.springframework.boot.web.reactive.context.ReactiveWebApplicationContext";
static WebApplicationType deduceFromClasspath() {
if (ClassUtils.isPresent(WEBFLUX_INDICATOR_CLASS, null)
&& !ClassUtils.isPresent(WEBMVC_INDICATOR_CLASS, null)
&& !ClassUtils.isPresent(JERSEY_INDICATOR_CLASS, null)) {
return WebApplicationType.REACTIVE;
}
for (String className : SERVLET_INDICATOR_CLASSES) {
if (!ClassUtils.isPresent(className, null)) {
return WebApplicationType.NONE;
}
}
return WebApplicationType.SERVLET;
}
三种返回类型解释:
- return WebApplicationType.NONE :不是Web应用程序
- return WebApplicationType.SERVLET :基于servlet的Web应用程序
- WebApplicationType.REACTIVE :响应式的Web应用程序
2.2 由接口获取其实现类的对象实例
private <T> Collection<T> getSpringFactoriesInstances(Class<T> type) {
return getSpringFactoriesInstances(type, new Class<?>[] {});
}
private <T> Collection<T> getSpringFactoriesInstances(Class<T> type,
Class<?>[] parameterTypes, Object... args) {
//获取类加载器
ClassLoader classLoader = getClassLoader();
//获取type的实现类的全限定名,存储在set中确保每一个全限定名是唯一的
Set<String> names = new LinkedHashSet<>(
SpringFactoriesLoader.loadFactoryNames(type, classLoader));
//创建type的实现类的对象
List<T> instances = createSpringFactoriesInstances(type, parameterTypes,
classLoader, args, names);
//进行排序
AnnotationAwareOrderComparator.sort(instances);
return instances;
}
3 执行run方法
SpringApplication构造完后就执行run
public ConfigurableApplicationContext run(String... args) {
//StopWatch是org.springframework.util的工具类,可以用来记录程序的运行时间
StopWatch stopWatch = new StopWatch();
stopWatch.start();
//spring容器
ConfigurableApplicationContext context = null;
Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
//设置SYSTEM_PROPERTY_JAVA_AWT_HEADLESS为true
configureHeadlessProperty();
//从META-INF/spring.factories文件中得到SpringApplicationRunListener接口的所有实现类对象实例集合
//该对象持有SpringApplicationRunListener对象的集合,统一管理SpringApplicationRunListener
SpringApplicationRunListeners listeners = getRunListeners(args);
//发布ApplicationStartingEvent事件,
listeners.starting();
//springboot启动时的事件驱动模型先到此
//----------------------------------------
//下面先不用管,下面是spring容器的创建
...
}
3.1 getRunListeners(String[] args)
private SpringApplicationRunListeners getRunListeners(String[] args) {
Class<?>[] types = new Class<?>[] { SpringApplication.class, String[].class };
//这里有从META-INF/spring.factories文件中获取SpringApplicationRunListener接口的实现类
//将类的对象实例传入SpringApplicationRunListeners的构造器中
return new SpringApplicationRunListeners(logger, getSpringFactoriesInstances(
SpringApplicationRunListener.class, types, this, args));
}
这里的getSpringFactoriesInstances方法比上面多了SpringApplication.class和String[].class组成的Class数组type、this、args,这些为创建SpringApplicationRunListener实现类对象时的参数。
3.1.1 SpringApplicationRunListeners的构造
SpringApplicationRunListeners(Log log,
Collection<? extends SpringApplicationRunListener> listeners) {
this.log = log;
this.listeners = new ArrayList<>(listeners);
}
3.2 listeners.starting()
public void starting() {
for (SpringApplicationRunListener listener : this.listeners) {
listener.starting();
}
}
public void starting() {
//this.initialMulticaster就是SimpleApplicationEventMulticaster
//使用SimpleApplicationEventMulticaster发布事件ApplicationStartingEvent
//ApplicationStartingEvent的source是SpringApplication
this.initialMulticaster.multicastEvent(
new ApplicationStartingEvent(this.application, this.args));
}
public void multicastEvent(ApplicationEvent event) {
//将ApplicationStartingEvent封装成ResolvableType
multicastEvent(event, resolveDefaultEventType(event));
}
ResolvableType对象
event 封装成ResolvableType,该类提供方法可以得到父类,接口,以及通用参数。四种方法的到该对象:
- forField(Field)
- forMethodParameter(Method, int)
- forMethodReturnType(Method)
- forClass(Class)
@Override
public void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) {
ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
//getApplicationListeners()是由ApplicationEvent和ResolvableType得到监听该种事件的ApplicationListener集合
for (final ApplicationListener<?> listener : getApplicationListeners(event, type)) {
Executor executor = getTaskExecutor();
if (executor != null) {
executor.execute(() -> invokeListener(listener, event));
}
else {
//执行监听器的响应方法
invokeListener(listener, event);
}
}
}
4 总结
启动springboot,先会实例化 SpringApplication ,再执行 SpringApplication 的 run 方法, run 方法里面通过 getRunListeners(args) 方法获得了在META-INF/spring.factories文件中实现SpringApplicationRunListener接口的类的对象实例集合。
遍历这个集合,执行每一个SpringApplicationRunListener 的starting() 方法,使用SimpleApplicationEventMulticaster 的 multicastEvent(event) 方法发布ApplicationStartingEvent 事件。
multicastEvent(event) 方法里通过getApplicationListeners(event, type) 找出事件的监听者,在通过invokeListener(listener, event) 执行监听者的的响应方法。