springboot版本 2.1.1
SpringApplication 实例化做了什么?
public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
// 加载器,一般是null
this.resourceLoader = resourceLoader;
Assert.notNull(primarySources, "PrimarySources must not be null");
//一般是springboot启动类
this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
//判断web环境是servlet还是reactive还是none
this.webApplicationType = WebApplicationType.deduceFromClasspath();
//获取所有springboot项目下面下的META-INF/spring.factories的ApplicationContextInitializer
setInitializers((Collection) getSpringFactoriesInstances(
ApplicationContextInitializer.class));
setListeners((Collection)
//获取所有springboot项目下面下的META-INF/spring.factories 的ApplicationListener
getSpringFactoriesInstances(ApplicationListener.class));
//这个做法有点意思,springboot创建一个异常,通过异常的堆栈拿到执行main方法的类
this.mainApplicationClass = deduceMainApplicationClass();
}
上面大概讲了springboot实例化做的事情,接下来细化下
怎么判断当前web环境是servlet还是reactive还是none
现在的web项目一般都是基于servlet,这是spring5的新特性之一:reactive是不依赖servlet,大概看了下reactive相关的包结构基本于springmvc差不多,但是没细看怎么做到不依赖servlet
WebApplicationType.deduceFromClasspath
static WebApplicationType deduceFromClasspath() {
//如果项目中有orgspringframework.web.reactive.DispatcherHandler的类
//而且没有org.glassfish.jersey.servlet.ServletContainer 和
//org.springframework.web.servlet.DispatcherServlet 那就当作当前web环境是reactive环境
if (ClassUtils.isPresent(WEBFLUX_INDICATOR_CLASS, null)
&& !ClassUtils.isPresent(WEBMVC_INDICATOR_CLASS, null)
&& !ClassUtils.isPresent(JERSEY_INDICATOR_CLASS, null)) {
return WebApplicationType.REACTIVE;
}
// "javax.servlet.Servlet和org.springframework.web.context.ConfigurableWebApplicationContext只要有一个类不存在就当作none,不是web项目
for (String className : SERVLET_INDICATOR_CLASSES) {
if (!ClassUtils.isPresent(className, null)) {
return WebApplicationType.NONE;
}
}
//web环境是servlet
return WebApplicationType.SERVLET;
}
总结就是判断reactive和servlet相关的类有没有在项目中依赖
获取所有springboot项目下面下的META-INF/spring.factories的ApplicationContextInitializer
//springboot初始化的代码
setInitializers((Collection) getSpringFactoriesInstances(
ApplicationContextInitializer.class));
private <T> Collection<T> getSpringFactoriesInstances(Class<T> type,
Class<?>[] parameterTypes, Object... args) {
//获取类加载器
ClassLoader classLoader = getClassLoader();
// Use names and ensure unique to protect against duplicates
//这个重要,去加载spring.factories
Set<String> names = new LinkedHashSet<>(
SpringFactoriesLoader.loadFactoryNames(type, classLoader));
//通过spring.factories获取到的全类名实例化对象
List<T> instances = createSpringFactoriesInstances(type, parameterTypes,
classLoader, args, names);
//排序
AnnotationAwareOrderComparator.sort(instances);
return instances;
}
怎么加载spring.factories
private static Map<String, List<String>> loadSpringFactories(@Nullable ClassLoader classLoader) {
//MultiValueMap 就是一个map,先从缓存中获取
MultiValueMap<String, String> result = cache.get(classLoader);
if (result != null) {
return result;
}
try {
//加载META-INF/spring.factories 中的数据,可能存在多个Spring.factories
//在扩展spring的时候也可以自己在META-INF 下面添加spring.factories
Enumeration<URL> urls = (classLoader != null ?
classLoader.getResources(FACTORIES_RESOURCE_LOCATION) :
ClassLoader.getSystemResources(FACTORIES_RESOURCE_LOCATION));
//这个是一个spring自定义的map但是没有具体的时候,因为其实里面是用一个Map<string,List>(这个list是LinkedList)来接
result = new LinkedMultiValueMap<>();
while (urls.hasMoreElements()) {
URL url = urls.nextElement();
UrlResource resource = new UrlResource(url);
Properties properties = PropertiesLoaderUtils.loadProperties(resource);
for (Map.Entry<?, ?> entry : properties.entrySet()) {
String factoryClassName = ((String) entry.getKey()).trim();
//用逗号分隔成多个(好像还有换行符)
for (String factoryName : StringUtils.commaDelimitedListToStringArray((String) entry.getValue())) {
result.add(factoryClassName, factoryName.trim());
}
}
}
//放到缓存中
cache.put(classLoader, result);
return result;
}
}
所以就是通过加载spring.factories得到key接口,value是实现类,同时放到缓存中,可以用来做spring扩展
//实例化 ApplicationContextInitializer 之后放到这个list
private List<ApplicationContextInitializer<?>> initializers;
//实例化 ApplicationListener 之后放到这个list
private List<ApplicationListener<?>> listeners;
上面就是springboot大概的实例化
run方法做了什么?
public ConfigurableApplicationContext run(String... args) {
.....
//获取监听器
SpringApplicationRunListeners listeners = getRunListeners(args);
//执行监听器
listeners.starting();
.......
}
getRunListeners(args) 这个方法做了什么
private SpringApplicationRunListeners getRunListeners(String[] args) {
Class<?>[] types = new Class<?>[] { SpringApplication.class, String[].class };
//从spring.factories 取出 SpringApplicationRunListener
目前只有 EventPublishingRunListener (其实并不是真实的监听器,往下看)
return new SpringApplicationRunListeners(logger, getSpringFactoriesInstances(
SpringApplicationRunListener.class, types, this, args));
}
listeners.starting() 其实是调用了EventPublishingRunListener#starting
public EventPublishingRunListener(SpringApplication application, String[] args) {
this.application = application;
this.args = args;
//EventPublishingRunListener实例化的时候,会创建一个广播器,然并且往广播//器放真实的监听,这些监听都是SpringApplicaition实例化的时候从spring.fac//tories拿出来的,后面需要通知监听器的时候就是使用广播器通知
this.initialMulticaster = new SimpleApplicationEventMulticaster();
for (ApplicationListener<?> listener : application.getListeners()) {
this.initialMulticaster.addApplicationListener(listener);
}
}
public void starting() {
//直接调用广播器
this.initialMulticaster.multicastEvent(
new ApplicationStartingEvent(this.application, this.args));
}
接下来看下 SimpleApplicationEventMulticaster#multicastEvent
@Override
public void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) {
ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
//通过 getApplicationListeners 获取符合条件的监听器
for (final ApplicationListener<?> listener : getApplicationListeners(event, type)) {
Executor executor = getTaskExecutor();
if (executor != null) {
executor.execute(() -> invokeListener(listener, event));
}
else {
//执行监听器的 onApplicationEvent 方法
invokeListener(listener, event);
}
}
}
getApplicationListeners 获取符合条件的监听器其实就是调用GenericApplicationListener#supportsEventType 来判断的,所以一般写spring监听器,就是实现 GenericApplicationListener#supportsEventType方法,来判断自己的监听对什么事件感兴趣
未完待续……….