spring boot可以简化配置,主要就是由自动装配实现,现在总结一篇详细的,之后在封装框架的时候用到。
本博客重点:
springboot工程的main函数中会添加一个SpringApplication.run,那么就从这里开始
以下为spring boot 2的代码
/**
* Create a new {@link SpringApplication} instance. The application context will load
* beans from the specified primary sources (see {@link SpringApplication class-level}
* documentation for details. The instance can be customized before calling
* {@link #run(String...)}.
* @param resourceLoader the resource loader to use
* @param primarySources the primary bean sources
* @see #run(Class, String[])
* @see #setSources(Set)
*/
@SuppressWarnings({ "unchecked", "rawtypes" })
public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
// 这里的resourceLoader是null
this.resourceLoader = resourceLoader;
// primarySources是入口类DemoApplication.class
Assert.notNull(primarySources, "PrimarySources must not be null");
// 制作成有序集合(为了去重和排序)
this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
// 使用WebApplication去探测application的类型
this.webApplicationType = WebApplicationType.deduceFromClasspath();
// 设置需要初始化的内容(这些内容都是通过扫描某个基类实现,下文将对getSpringFactoriesInstances进行阐述)
setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
// 设置监听内容
setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
// 检测入口class是哪个(这里当然就是DemoApplication了)
this.mainApplicationClass = deduceMainApplicationClass();
}
大家要问了,设置启动内容和监听内容显然是构造的重点,下文又是怎么利用的呢?我们来继续看下,这里可以直接看getSpringFactoriesInstances方法。
private <T> Collection<T> getSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes, Object... args) {
// 获取classLoader,从debug来看,这里是AppClassLoader(最终是ClassUtils.getDefaultClassLoader中获取)
ClassLoader classLoader = getClassLoader();
// Use names and ensure unique to protect against duplicates
Set<String> names = new LinkedHashSet<>(SpringFactoriesLoader.loadFactoryNames(type, classLoader));
// 根据类名创建实例(也就是说,谁实现或者继承了这个基类或者接口,都会被实例化出来,最终返回)
List<T> instances = createSpringFactoriesInstances(type, parameterTypes, classLoader, args, names);
AnnotationAwareOrderComparator.sort(instances);
return instances;
}
推测
这个时候logger也创建的差不多了。。)BeanUtils
进行实例化(重点是BeanUtils实例化的对象将进入spring容器)开始启动
消息,注意,这里是异步消息运行中
消息,注意,这里是异步消息
通过上述流程最终调用到以下代码。
SimpleApplicationEventMulticaster主要依赖两个:
注:需要了解springframework:spring-context的包
@Override
public void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) {
ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
Executor executor = getTaskExecutor();
for (ApplicationListener<?> listener : getApplicationListeners(event, type)) {
if (executor != null) {
executor.execute(() -> invokeListener(listener, event));
}
else {
invokeListener(listener, event);
}
}
}
@SuppressWarnings({"rawtypes", "unchecked"})
private void doInvokeListener(ApplicationListener listener, ApplicationEvent event) {
try {
listener.onApplicationEvent(event);
}
catch (ClassCastException ex) {
String msg = ex.getMessage();
if (msg == null || matchesClassCastMessage(msg, event.getClass())) {
// Possibly a lambda-defined listener which we could not resolve the generic event type for
// -> let's suppress the exception and just log a debug message.
Log logger = LogFactory.getLog(getClass());
if (logger.isTraceEnabled()) {
logger.trace("Non-matching event type for listener: " + listener, ex);
}
}
else {
throw ex;
}
}
}
最终调用到doInvokeListener,回调给上层的onApplicationEvent
注:准备环境的过程主要是加载配置(自定义配置、系统配置)
待续。。。。