上篇回顾
上一篇初始化SpringApplication实例, 我们实例化了一个SpringApplication实例,整个流程共计4步
- 调用WebApplicationType.deduceFromClasspath方法, 获取Web类型
- 通过getSpringFactoriesInstances()方法, 调用SpringFactoriesLoader.loadFactoryNames, 首先加载META-INF/spring.factories配置的类名到缓存中, 之后实例化了ApplicationContextInitializer的子类列表, 赋值给SpringApplication的initializers列表
- 通过getSpringFactoriesInstances()方法, 调用SpringFactoriesLoader.loadFactoryNames,从SpringFactoriesLoader的缓存中获取并实例化ApplicationListener子类列表, 赋值SpringApplication的listeners列表
- 通过抛出一个RuntimeException, 遍历其堆栈信息, 获取到类名中包含main方法的类, 实例化这个类, 赋值给SpringApplication的mainApplicationClass对象
目录
1. 发布启动事件ApplicationStartingEvent
1.1 SpringApplicationRunListeners源码
1.2 EventPublishingRunListener源码
1.3 SimpleApplicationEventMulticaster源码
2. 启动事件的监听器
2.1 LoggingApplicationListener
2.2 BackgroundPreinitializer
2.3 DelegatingApplicationListener
2.4 LiquibaseServiceLocatorApplicationListener
3. 总结
1. 发布启动事件ApplicationStartingEvent
调用getRunListeners()方法, 实例化一个SpringApplicationRunListeners对象, SpringApplicationRunListeners的构造参数通过getSpringFactoriesInstances()方法获得,这个方法在之前分析过了, 获取的一个EventPublishingRunListener对象, 所以调用的是EventPublishingRunListener#starting()方法
public class SpringApplication {
//run方法
public ConfigurableApplicationContext run(String... args) {
StopWatch stopWatch = new StopWatch();
stopWatch.start();
ConfigurableApplicationContext context = null;
Collection exceptionReporters = new ArrayList<>();
configureHeadlessProperty();
//本文分析的重点,发布启动事件ApplicationStartingEvent
//获取SpringApplicationRunListener的子类listener
SpringApplicationRunListeners listeners = getRunListeners(args);
//执行其starting()方法
listeners.starting();
....
}
//获取SpringApplicationRunListener的子类listener
private SpringApplicationRunListeners getRunListeners(String[] args) {
Class>[] types = new Class>[] { SpringApplication.class, String[].class };
//调用getSpringFactoriesInstances方法
//获取SpringApplicationRunListener的子类
//子类只有一个,EventPublishingRunListener
//实例化了一个SpringApplicationRunListeners对象
return new SpringApplicationRunListeners(logger, getSpringFactoriesInstances(
SpringApplicationRunListener.class, types, this, args));
}
}
1.1 SpringApplicationRunListeners源码
SpringApplicationRunListeners是一个比较重要的类, 之后的代码会经常调用这个方法, 内部封装了一个SpringApplicationRunListener的list, 方便以后扩展, 目前只有一个EventPublishingRunListener实例, 所以spring的事件都是由EventPublishingRunListener发布的
//SpringApplicationRunListeners部分源码
class SpringApplicationRunListeners {
private final Log log;
//SpringApplicationRunListener的子类对象列表
//listener列表扩展点
private final List listeners;
SpringApplicationRunListeners(Log log,
Collection extends SpringApplicationRunListener> listeners) {
this.log = log;
this.listeners = new ArrayList<>(listeners);
}
//发布启动事件
public void starting() {
for (SpringApplicationRunListener listener : this.listeners) {
//目前调用EventPublishingRunListener#starting方法
listener.starting();
}
}
//其他事件都是相同的代码
//....
}
1.2 EventPublishingRunListener源码
EventPublishingRunListener是springboot的事件广播器, 内部封装了一个SimpleApplicationEventMulticaster对象, 用来发布springboot加载过程中的各个事件
- 事件源SpringApplication对象
- 事件SpringApplicationEvent对象
- 事件发布器是EventPublishingRunListener, 正在的事件发布器是其内部SimpleApplicationEventMulticaster成员变量
- 事件监听器SpringApplication维护的listeners, 调用AbstractApplicationEventMulticaster#getApplicationListeners(ApplicationEvent, ResolvableType)筛选出支持ApplicationEvent的listeners
//EventPublishingRunListener部分源码
public class EventPublishingRunListener implements SpringApplicationRunListener, Ordered {
//SpringApplication对象
private final SpringApplication application;
//命令函参数
private final String[] args;
//事件广播器
private final SimpleApplicationEventMulticaster initialMulticaster;
public EventPublishingRunListener(SpringApplication application, String[] args) {
this.application = application;
this.args = args;
this.initialMulticaster = new SimpleApplicationEventMulticaster();
// 通过application.getListeners(),获取到Listener列表
// ConfigFileApplicationListener
// AnsiOutputApplicationListener
// LoggingApplicationListener
// ClasspathLoggingApplicationListener
// BackgroundPreinitializer
// DelegatingApplicationListener
// ParentContextCloserApplicationListener
// ClearCachesApplicationListener
// FileEncodingApplicationListener
// LiquibaseServiceLocatorApplicationListener
for (ApplicationListener> listener : application.getListeners()) {
//将listener添加到事件广播器initialMulticaster
this.initialMulticaster.addApplicationListener(listener);
}
}
@Override
public void starting() {
// 广播器广播ApplicationStartingEvent事件
this.initialMulticaster.multicastEvent(
new ApplicationStartingEvent(this.application, this.args));
}
//其他事件发布都是相同的代码
//...
}
1.3 SimpleApplicationEventMulticaster源码
springboot默认事件广播器, 有三个重要方法, 用于发布spring启动过程中的各个事件
- addApplicationListener() 添加监听器listener
- multicastEvent() 广播spring事件
- invokeListener() 实现每个listener的onApplicationEvent()方法
父类AbstractApplicationEventMulticaster
封装了四个重要方法:
- addApplicationListener添加listener
- addApplicationListenerBean添加注入的listener bean名称
- removeApplicationListener删除listener
- removeApplicationListenerBean删除注入的listener bean名称
- getApplicationListeners()先从缓存retrieverCache获取listener,如果缓存不存在, 封装数据放入缓存中, 增删listener的时候, 缓存retrieverCache会被清空
//抽象事件广播器
public abstract class AbstractApplicationEventMulticaster
implements ApplicationEventMulticaster, BeanClassLoaderAware, BeanFactoryAware {
//监听器遍历器
//成员变量applicationListeners Set维护了application中包含的listeners,
//成员变量applicationListenerBeans Set维护了注入的listener bean名称
private final ListenerRetriever defaultRetriever = new ListenerRetriever(false);
//调用getApplicationListeners()方法之后
//缓存spring事件以及对应的listener列表
final Map retrieverCache = new ConcurrentHashMap<>(64);
private Object retrievalMutex = this.defaultRetriever;
@Override
public void addApplicationListener(ApplicationListener> listener) {
synchronized (this.retrievalMutex) {
//监听器已经被加载过,
//先执行删除操作,防止重复执行
Object singletonTarget = AopProxyUtils.getSingletonTarget(listener);
if (singletonTarget instanceof ApplicationListener) {
this.defaultRetriever.applicationListeners.remove(singletonTarget);
}
this.defaultRetriever.applicationListeners.add(listener);
//清空缓存
this.retrieverCache.clear();
}
}
/**
* 获取支持监听event的listener
* 这里使用了单例模式
*/
protected Collection> getApplicationListeners(
ApplicationEvent event, ResolvableType eventType) {
Object source = event.getSource();
Class> sourceType = (source != null ? source.getClass() : null);
ListenerCacheKey cacheKey = new ListenerCacheKey(eventType, sourceType);
//尝试从ConcurrentHashMap缓存中取出listener列表
ListenerRetriever retriever = this.retrieverCache.get(cacheKey);
if (retriever != null) {
return retriever.getApplicationListeners();
}
if (this.beanClassLoader == null ||
(ClassUtils.isCacheSafe(event.getClass(), this.beanClassLoader) &&
(sourceType == null || ClassUtils.isCacheSafe(sourceType, this.beanClassLoader)))) {
//双重检查锁定
//当多线程访问的时候,
//之前retriever多个线程否返回null,
//此时锁住this.retrievalMutex
//防止多次实例化
synchronized (this.retrievalMutex) {
//再尝试从cache中获取
retriever = this.retrieverCache.get(cacheKey);
if (retriever != null) {
return retriever.getApplicationListeners();
}
//生成Key和Value放入缓存中
retriever = new ListenerRetriever(true);
Collection> listeners =
retrieveApplicationListeners(eventType, sourceType, retriever);
this.retrieverCache.put(cacheKey, retriever);
return listeners;
}
}
else {
//没有缓存ListenerRetriever,那么就不需要同步
return retrieveApplicationListeners(eventType, sourceType, null);
}
}
//retrieveApplicationListeners方法中
//调用了supportsEvent方法
//supportsEvent使用了适配器模式
protected boolean supportsEvent(
ApplicationListener> listener, ResolvableType eventType, @Nullable Class> sourceType) {
GenericApplicationListener smartListener = (listener instanceof GenericApplicationListener ?
(GenericApplicationListener) listener : new GenericApplicationListenerAdapter(listener));
return (smartListener.supportsEventType(eventType) && smartListener.supportsSourceType(sourceType));
}
}
SimpleApplicationEventMulticaster
广播事件, 然后实现每个listener的onApplicationEvent()方法
public class SimpleApplicationEventMulticaster extends AbstractApplicationEventMulticaster {
@Nullable
private Executor taskExecutor;
@Nullable
private ErrorHandler errorHandler;
/**
* 构造函数
* taskExecutor和errorHandler都是null
*/
public SimpleApplicationEventMulticaster() {
}
/**
* 广播事件
* @param event 事件
* @param eventType 事件类型
*/
@Override
public void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) {
ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
//调用父类getApplicationListeners方法
//遍历所有支持ApplicationStartingEvent事件的监听器
//LoggingApplicationListener
//BackgroundPreinitializer
//DelegatingApplicationListener
//LiquibaseServiceLocatorApplicationListener
for (final ApplicationListener> listener : getApplicationListeners(event, type)) {
//此时的executor为null
Executor executor = getTaskExecutor();
if (executor != null) {
executor.execute(() -> invokeListener(listener, event));
}
else {
//调用listener
invokeListener(listener, event);
}
}
}
/**
* 具体调用监听器的方法
* @param listener 监听器
* @param event 事件
*/
private void doInvokeListener(ApplicationListener listener, ApplicationEvent event) {
try {
//调用listener的onApplicationEvent方法
listener.onApplicationEvent(event);
}
catch (ClassCastException ex) {
String msg = ex.getMessage();
if (msg == null || matchesClassCastMessage(msg, event.getClass())) {
Log logger = LogFactory.getLog(getClass());
if (logger.isDebugEnabled()) {
logger.debug("Non-matching event type for listener: " + listener, ex);
}
}
else {
throw ex;
}
}
}
}
2. 启动事件的监听器
对Spring启动事件ApplicationStartingEvent感兴趣的Listener:
- LoggingApplicationListener 日志监听器,配置日志
- BackgroundPreinitializer 后台初始化器, 多线程加载耗时任务
- DelegatingApplicationListener 代理监听器, 继续发布事件
- LiquibaseServiceLocatorApplicationListener 将liquibas替换为可以和spring配合工作的版本
2.1 LoggingApplicationListener部分代码
获取当前应用使用的日志系统, 初始化loggingSystem, 调用loggingSystem的beforeInitialize方法, 开启日志的准备工作
public class LoggingApplicationListener implements GenericApplicationListener {
//处理starting事件
if (event instanceof ApplicationStartingEvent) {
onApplicationStartingEvent((ApplicationStartingEvent) event);
}
}
//日志系统准备工作
private void onApplicationStartingEvent(ApplicationStartingEvent event) {
//1.获取模块使用的日志系统
this.loggingSystem = LoggingSystem
.get(event.getSpringApplication().getClassLoader());
//2.日志系统准备工作
//调用的是LogbackLoggingSystem#beforeInitialize
this.loggingSystem.beforeInitialize();
}
}
LoggingSystem
spring支持logback, Log4j, JDK logging, 有两个重要方法
- get() 获取应用使用的日志系统
- beforeInitialize()获取
springboot默认使用logback, 也就是LogbackLoggingSystem
/**
*日志系统的父类
*/
public abstract class LoggingSystem {
public static final String SYSTEM_PROPERTY = LoggingSystem.class.getName();
//Spring支持的几种日志系统
private static final Map SYSTEMS;
static {
Map systems = new LinkedHashMap<>();
//1.logback
systems.put("ch.qos.logback.core.Appender",
"org.springframework.boot.logging.logback.LogbackLoggingSystem");
//2.Log4j
systems.put("org.apache.logging.log4j.core.impl.Log4jContextFactory",
"org.springframework.boot.logging.log4j2.Log4J2LoggingSystem");
//3.JDK logging
systems.put("java.util.logging.LogManager",
"org.springframework.boot.logging.java.JavaLoggingSystem");
SYSTEMS = Collections.unmodifiableMap(systems);
}
/**
* 判断并返回模块使用的日志系统
* 我们应用使用的是logback
* @param classLoader 加载SpringApplication的classloader
*/
public static LoggingSystem get(ClassLoader classLoader) {
String loggingSystem = System.getProperty(SYSTEM_PROPERTY);
if (StringUtils.hasLength(loggingSystem)) {
if (NONE.equals(loggingSystem)) {
return new NoOpLoggingSystem();
}
return get(classLoader, loggingSystem);
}
//使用加载SpringApplication的classloader去加载支持的日志
//如果能加载一个或者多个,返回第一个
//否则就抛出异常
return SYSTEMS.entrySet().stream()
.filter((entry) -> ClassUtils.isPresent(entry.getKey(), classLoader))
.map((entry) -> get(classLoader, entry.getValue())).findFirst()
.orElseThrow(() -> new IllegalStateException(
"No suitable logging system located"));
}
}
/**
* logback日志系统
* 继承了Sfl4j日志系统
*/
public class LogbackLoggingSystem extends Slf4JLoggingSystem {
@Override
public void beforeInitialize() {
//获取LoggerContext
LoggerContext loggerContext = getLoggerContext();
//如果logger已经被初始化,name直接返回
if (isAlreadyInitialized(loggerContext)) {
return;
}
//调用父类的beforeInitialize方法
//默认使用debug模式
super.beforeInitialize();
loggerContext.getTurboFilterList().add(FILTER);
}
}
2.2 BackgroundPreinitializer
Spring会在项目启动的时候,默认开启线程加载一些耗时的任务,这样可以加快启动速度
@Order(LoggingApplicationListener.DEFAULT_ORDER + 1)
public class BackgroundPreinitializer
implements ApplicationListener {
//系统属性用来配置是够需要忽略预加载
public static final String IGNORE_BACKGROUNDPREINITIALIZER_PROPERTY_NAME = "spring.backgroundpreinitializer.ignore";
//预加载是否执行,启动原子布尔类型,默认为false
private static final AtomicBoolean preinitializationStarted = new AtomicBoolean(
false);
//同步工具
private static final CountDownLatch preinitializationComplete = new CountDownLatch(1);
}
2.3 DelegatingApplicationListener
扩展点, 可以继续广播事件, 查找属性context.listener.classes对应的listener名称列表, 实例化代理监听器, 继续广播事件, 当前应用中没有做任何操作
public class DelegatingApplicationListener
implements ApplicationListener, Ordered {
private static final String PROPERTY_NAME = "context.listener.classes";
//默认为null
private SimpleApplicationEventMulticaster multicaster;
@Override
public void onApplicationEvent(ApplicationEvent event) {
if (event instanceof ApplicationEnvironmentPreparedEvent) {
//监听到EnvironmentPreparedEvent事件
List> delegates = getListeners(
((ApplicationEnvironmentPreparedEvent) event).getEnvironment());
if (delegates.isEmpty()) {
return;
}
this.multicaster = new SimpleApplicationEventMulticaster();
for (ApplicationListener listener : delegates) {
this.multicaster.addApplicationListener(listener);
}
}
if (this.multicaster != null) {
//再次发送事件
this.multicaster.multicastEvent(event);
}
}
//生成并返回Listener
private List> getListeners(
ConfigurableEnvironment environment) {
if (environment == null) {
return Collections.emptyList();
}
//获取属性名称对应的事件监听器名称
String classNames = environment.getProperty(PROPERTY_NAME);
List> listeners = new ArrayList<>();
if (StringUtils.hasLength(classNames)) {
for (String className : StringUtils.commaDelimitedListToSet(classNames)) {
try {
//反射生成对象
//放入监听器列表中
Class> clazz = ClassUtils.forName(className,
ClassUtils.getDefaultClassLoader());
Assert.isAssignable(ApplicationListener.class, clazz, "class ["
+ className + "] must implement ApplicationListener");
listeners.add((ApplicationListener) BeanUtils
.instantiateClass(clazz));
}
catch (Exception ex) {
throw new ApplicationContextException(
"Failed to load context listener class [" + className + "]",
ex);
}
}
}
AnnotationAwareOrderComparator.sort(listeners);
return listeners;
}
}
2.4 LiquibaseServiceLocatorApplicationListener
public class LiquibaseServiceLocatorApplicationListener
implements ApplicationListener {
if (ClassUtils.isPresent("liquibase.servicelocator.CustomResolverServiceLocator",
event.getSpringApplication().getClassLoader())) {
//将liquibas替换为 可以和spring配合工作的版本
new LiquibasePresent().replaceServiceLocator();
}
}
3. 总结
- 首先调用getRunListeners()方法, 获得一个SpringApplicationRunListeners对象,
- SpringApplicationRunListeners的成员变量listeners是通过getSpringFactoriesInstances()方法获取的SpringApplicationRunListener子类列表
- 当前只能获取EventPublishingRunListener,
- 调用SpringApplicationRunListeners对象的starting()方法, 发布SpringApplication启动事件
- 内部EventPublishingRunListener#starting()方法
- 最终调用SimpleApplicationEventMulticaster#multicastEvent()方法
- 发布了ApplicationStartingEvent事件, 最后执行每个监听器的onApplicationEvent方法
- 对ApplicationStartingEvent事件感兴趣的监听器
- LoggingApplicationListener 日志监听器,配置日志
- BackgroundPreinitializer 后台初始化器, 多线程加载耗时任务
- DelegatingApplicationListener 代理监听器, 继续发布事件
- LiquibaseServiceLocatorApplicationListener 将liquibas替换为可以和spring配合工作的版本
下一篇
我们将会在下一篇封装命令行参数DefaultApplicationArguments, 继续研究springboot的启动流程