监听器 && WebServerInitializedEvent
参考:mica 项目 如梦技术 / mica
监听事件的方式
事件
public class DemoEvent extends ApplicationEvent {
public DemoEvent(Object source) {
super(source);
}
}
Listener
public class DemoListener implements ApplicationListener {
@Override
public void onApplicationEvent(ApplicationEvent event) {
}
}
方式一 手动添加
public class DemoApplication {
public static void main(String[] args) {
ConfigurableApplicationContext applicationContext = SpringApplication.run(DemoApplication.class, args);
applicationContext.addApplicationListener(new DemoListener());
}
}
方式二 注入容器管理
@Component
public class DemoListener implements ApplicationListener
方式三 注解
@Component
public class DemoListener {
@EventListener
public void listen(ApplicationEvent event) {
}
}
指定顺序
默认按照 bean 自然装载的顺序执行的
SmartApplicationListener
是一个接口,继承 Ordered 接口
public interface SmartApplicationListener extends ApplicationListener<ApplicationEvent>, Ordered {
boolean supportsEventType(Class<? extends ApplicationEvent> eventType);
default boolean supportsSourceType(@Nullable Class<?> sourceType) {
return true;
}
@Override
default int getOrder() {
return LOWEST_PRECEDENCE;
}
default String getListenerId() {
return "";
}
}
PriorityOrdered
优先级排序,在普通 Ordered 之前被 应用apply
public interface PriorityOrdered extends Ordered {
}
值越小,优先级越高
public interface Ordered {
int HIGHEST_PRECEDENCE = Integer.MIN_VALUE;
int LOWEST_PRECEDENCE = Integer.MAX_VALUE;
int getOrder();
}
OrderComparator
比较器,继承了 PriorityOrdered 相比其他优先级永远更高。
private int doCompare(@Nullable Object o1, @Nullable Object o2, @Nullable OrderSourceProvider sourceProvider) {
boolean p1 = (o1 instanceof PriorityOrdered);
boolean p2 = (o2 instanceof PriorityOrdered);
if (p1 && !p2) {
return -1;
}
else if (p2 && !p1) {
return 1;
}
int i1 = getOrder(o1, sourceProvider);
int i2 = getOrder(o2, sourceProvider);
return Integer.compare(i1, i2);
}
@Component
public class DemoListener implements SmartApplicationListener {
@Override
public boolean supportsEventType(Class<? extends ApplicationEvent> eventType) {
return eventType == DemoEvent.class;
}
@Override
public void onApplicationEvent(ApplicationEvent event) {
}
@Override
public int getOrder() {
return -2;
}
}
@Order
@Component
public class DemoListener {
@Order(-2)
@EventListener
public void listen(ApplicationEvent event) {
}
}
异步执行
默认通知线程和监听线程是一个线程,同步执行逻辑。
@Async
@Component
public class DemoListener {
@Order(-2)
@EventListener
@Async
public void listen(ApplicationEvent event) {
}
}
原理
ApplicationEvent
继承了 JDK 的 EventObject,加上时间戳字段
public abstract class ApplicationEvent extends EventObject {
private final long timestamp;
}
public class EventObject implements java.io.Serializable {
/**
* The object on which the Event initially occurred.
*/
protected transient Object source;
}
ApplicationListener
继承 JDK 的 EventListener(标记接口,没有方法)
@FunctionalInterface
public interface ApplicationListener<E extends ApplicationEvent> extends EventListener {
void onApplicationEvent(E event);
static <T> ApplicationListener<PayloadApplicationEvent<T>> forPayload(Consumer<T> consumer) {
return event -> consumer.accept(event.getPayload());
}
}
ApplicationEventMulticaster
事件管理者,管理监听器和发布事件,ApplicationContext通过委托ApplicationEventMulticaster来 发布事件
public interface ApplicationEventMulticaster {
void addApplicationListener(ApplicationListener<?> listener);
void addApplicationListenerBean(String listenerBeanName);
void removeApplicationListener(ApplicationListener<?> listener);
void removeApplicationListenerBean(String listenerBeanName);
void removeApplicationListeners(Predicate<ApplicationListener<?>> predicate);
void removeApplicationListenerBeans(Predicate<String> predicate);
void removeAllListeners();
void multicastEvent(ApplicationEvent event);
void multicastEvent(ApplicationEvent event, @Nullable ResolvableType eventType);
}
ApplicationEventPublisher
事件发布者,该接口封装了事件有关的公共方法,作为ApplicationContext的超级街廓,也是委托 ApplicationEventMulticaster完成事件发布。
public interface ApplicationEventPublisher {
default void publishEvent(ApplicationEvent event) {
publishEvent((Object) event);
}
void publishEvent(Object event);
}
ApplicationEventMulticaster
AbstractApplicationEventMulticaster
实现类监听器管理的逻辑
只列出了新增,删除基本一致的逻辑
public abstract class AbstractApplicationEventMulticaster
implements ApplicationEventMulticaster, BeanClassLoaderAware, BeanFactoryAware {
private final DefaultListenerRetriever defaultRetriever = new DefaultListenerRetriever();
final Map<ListenerCacheKey, CachedListenerRetriever> retrieverCache = new ConcurrentHashMap<>(64);
@Override
public void addApplicationListener(ApplicationListener<?> listener) {
synchronized (this.defaultRetriever) {
// 被代理过则删除未被代理时的, 加入代理后的
Object singletonTarget = AopProxyUtils.getSingletonTarget(listener);
if (singletonTarget instanceof ApplicationListener) {
this.defaultRetriever.applicationListeners.remove(singletonTarget);
}
this.defaultRetriever.applicationListeners.add(listener);
this.retrieverCache.clear();
}
}
@Override
public void addApplicationListenerBean(String listenerBeanName) {
synchronized (this.defaultRetriever) {
this.defaultRetriever.applicationListenerBeans.add(listenerBeanName);
this.retrieverCache.clear();
}
}
protected Collection<ApplicationListener<?>> getApplicationListeners() {
synchronized (this.defaultRetriever) {
return this.defaultRetriever.getApplicationListeners();
}
}
}
public abstract class AbstractApplicationEventMulticaster
implements ApplicationEventMulticaster, BeanClassLoaderAware, BeanFactoryAware {
private final DefaultListenerRetriever defaultRetriever = new DefaultListenerRetriever();
final Map<ListenerCacheKey, CachedListenerRetriever> retrieverCache = new ConcurrentHashMap<>(64);
@Nullable
private ClassLoader beanClassLoader;
@Nullable
private ConfigurableBeanFactory beanFactory;
protected Collection<ApplicationListener<?>> getApplicationListeners(
ApplicationEvent event, ResolvableType eventType) {
// 逻辑有点复杂, 暂略
// 就是查询出支持事件源和事件的监听器列表, 并缓存下来
}
private class DefaultListenerRetriever {
public final Set<ApplicationListener<?>> applicationListeners = new LinkedHashSet<>();
public final Set<String> applicationListenerBeans = new LinkedHashSet<>();
public Collection<ApplicationListener<?>> getApplicationListeners() {
// applicationListeners && beanFactory 的 applicationListenerBeans
// 都必须是 ApplicationListener 类型的
}
}
}
SimpleApplicationEventMulticaster
实现了发布事件的逻辑
public class SimpleApplicationEventMulticaster extends AbstractApplicationEventMulticaster {
// 有则使用线程池执行, 没有则直接调用
@Nullable
private Executor taskExecutor;
// 异常处理
@Nullable
private ErrorHandler errorHandler;
}
public class SimpleApplicationEventMulticaster extends AbstractApplicationEventMulticaster {
@Override
public void multicastEvent(ApplicationEvent event) {
multicastEvent(event, resolveDefaultEventType(event));
}
@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);
}
}
}
private ResolvableType resolveDefaultEventType(ApplicationEvent event) {
return ResolvableType.forInstance(event);
}
protected void invokeListener(ApplicationListener<?> listener, ApplicationEvent event) {
ErrorHandler errorHandler = getErrorHandler();
// 错误处理器
if (errorHandler != null) {
try {
doInvokeListener(listener, event);
}
catch (Throwable err) {
errorHandler.handleError(err);
}
}
else {
doInvokeListener(listener, event);
}
}
@SuppressWarnings({"rawtypes", "unchecked"})
private void doInvokeListener(ApplicationListener listener, ApplicationEvent event) {
try {
listener.onApplicationEvent(event);
}
catch (ClassCastException ex) {
// 略
}
}
}
ApplicationEventPublisher
AbstractApplicationContext
ApplicationContext 继承并实现了它,容器本身就具有了发布事件的能力
public abstract class AbstractApplicationContext extends DefaultResourceLoader
implements ConfigurableApplicationContext {
@Override
public void publishEvent(ApplicationEvent event) {
publishEvent(event, null);
}
protected void publishEvent(Object event, @Nullable ResolvableType eventType) {
ApplicationEvent applicationEvent;
if (event instanceof ApplicationEvent) {
applicationEvent = (ApplicationEvent) event;
}
else {
applicationEvent = new PayloadApplicationEvent<>(this, event);
if (eventType == null) {
eventType = ((PayloadApplicationEvent<?>) applicationEvent).getResolvableType();
}
}
// Multicast right now if possible - or lazily once the multicaster is initialized
// multicaster 未初始化之前
if (this.earlyApplicationEvents != null) {
this.earlyApplicationEvents.add(applicationEvent);
}
else {
getApplicationEventMulticaster().multicastEvent(applicationEvent, eventType);
}
// Publish event via parent context as well...
if (this.parent != null) {
if (this.parent instanceof AbstractApplicationContext) {
((AbstractApplicationContext) this.parent).publishEvent(event, eventType);
}
else {
this.parent.publishEvent(event);
}
}
}
@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");
// Prepare this context for refreshing.
// 相当于第一步就是这个
prepareRefresh();
}
protected void prepareRefresh() {
// 其他
this.earlyApplicationEvents = new LinkedHashSet<>();
}
// Allows post-processing of the bean factory in context subclasses.
postProcessBeanFactory(beanFactory);
StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");
// Invoke factory processors registered as beans in the context.
invokeBeanFactoryPostProcessors(beanFactory);
// Register bean processors that intercept bean creation.
registerBeanPostProcessors(beanFactory);
beanPostProcess.end();
// Initialize message source for this context.
initMessageSource();
// Initialize event multicaster for this context.
// 这里初始化 multicaster
initApplicationEventMulticaster();
// Initialize other special beans in specific context subclasses.
onRefresh();
// Check for listener beans and register them.
// 在这里注册 listener, 并将 earlyApplicationEvents 置空
registerListeners();
// Instantiate all remaining (non-lazy-init) singletons.
finishBeanFactoryInitialization(beanFactory);
// Last step: publish corresponding event.
finishRefresh();
protected void registerListeners() {
// Register statically specified listeners first.
for (ApplicationListener<?> listener : getApplicationListeners()) {
getApplicationEventMulticaster().addApplicationListener(listener);
}
String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
for (String listenerBeanName : listenerBeanNames) {
getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
}
// Publish early application events now that we finally have a multicaster...
// 之前发布的事件, 但是由于未初始化完毕, 现在才发出
Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;
this.earlyApplicationEvents = null;
if (!CollectionUtils.isEmpty(earlyEventsToProcess)) {
for (ApplicationEvent earlyEvent : earlyEventsToProcess) {
getApplicationEventMulticaster().multicastEvent(earlyEvent);
}
}
}
有则使用,没有则新建
protected void initApplicationEventMulticaster() {
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) {
this.applicationEventMulticaster =
beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class);
}
else {
this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster);
}
}
Listener 发现机制
new add
直接 new 然后放到 AbstractApplicationContext 容器的
EventMulticaster 已初始化则直接放进去,没有则放在 applicationListeners,待 EventMulticaster 初始化时放入
看方法应该是不存在线程安全的,或者调用方不要在异步线程调用。
public void AbstractApplicationContext.addApplicationListener(ApplicationListener<?> listener) {
if (this.applicationEventMulticaster != null) {
this.applicationEventMulticaster.addApplicationListener(listener);
}
this.applicationListeners.add(listener);
}
@Component
AbstractApplicationContext#registerListeners 中先获取上面 applicationListeners 的,然后再获取容器中的 getBeanNamesForType。
@EventListener
EventListenerMethodProcessor
虽然是 BeanFactoryPostProcessor,但是在 SmartInitializingSingleton 处理的 @EventListener
public class EventListenerMethodProcessor
implements SmartInitializingSingleton, ApplicationContextAware, BeanFactoryPostProcessor {
public interface SmartInitializingSingleton {
void afterSingletonsInstantiated();
}
DefaultListableBeanFactory
@Override
public void preInstantiateSingletons() throws BeansException {
List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);
// Trigger initialization of all non-lazy singleton beans...
for (String beanName : beanNames) {
getBean & 实例化
}
// Trigger post-initialization callback for all applicable beans...
// 所有准备好后
for (String beanName : beanNames) {
Object singletonInstance = getSingleton(beanName);
if (singletonInstance instanceof SmartInitializingSingleton) {
SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
smartSingleton.afterSingletonsInstantiated();
}
}
}
但是为什么是在 registerListeners 后调用的
// Check for listener beans and register them.
registerListeners();
// Instantiate all remaining (non-lazy-init) singletons.
finishBeanFactoryInitialization(beanFactory);
// Last step: publish corresponding event.
finishRefresh();
private void processBean(final String beanName, final Class<?> targetType) {
Map<Method, EventListener> annotatedMethods = null;
annotatedMethods = MethodIntrospector.selectMethods(targetType,
(MethodIntrospector.MetadataLookup<EventListener>) method ->
AnnotatedElementUtils.findMergedAnnotation(method, EventListener.class));
// Non-empty set of methods
ConfigurableApplicationContext context = this.applicationContext;
List<EventListenerFactory> factories = this.eventListenerFactories;
for (Method method : annotatedMethods.keySet()) {
for (EventListenerFactory factory : factories) {
if (factory.supportsMethod(method)) {
Method methodToUse = AopUtils.selectInvocableMethod(method, context.getType(beanName));
ApplicationListener<?> applicationListener =
// 这里适配了, 适配器模式
factory.createApplicationListener(beanName, targetType, methodToUse);
if (applicationListener instanceof ApplicationListenerMethodAdapter) {
((ApplicationListenerMethodAdapter) applicationListener).init(context, this.evaluator);
}
context.addApplicationListener(applicationListener);
break;
}
}
}
}
ApplicationListenerMethodAdapter
public interface GenericApplicationListener extends SmartApplicationListener {
@Override
default boolean supportsEventType(Class<? extends ApplicationEvent> eventType) {
return supportsEventType(ResolvableType.forClass(eventType));
}
boolean supportsEventType(ResolvableType eventType);
}
public class ApplicationListenerMethodAdapter implements GenericApplicationListener {
public ApplicationListenerMethodAdapter(String beanName, Class<?> targetClass, Method method) {
// @EventListener
EventListener ann = AnnotatedElementUtils.findMergedAnnotation(this.targetMethod, EventListener.class);
// 事件类型
this.declaredEventTypes = resolveDeclaredEventTypes(method, ann);
// 条件
this.condition = (ann != null ? ann.condition() : null);
// order
this.order = resolveOrder(this.targetMethod);
}
// supportsEventType 略
@Override
public void onApplicationEvent(ApplicationEvent event) {
processEvent(event);
}
public void processEvent(ApplicationEvent event) {
Object[] args = resolveArguments(event);
// condition 处理
if (shouldHandle(event, args)) {
Object result = doInvoke(args);
}
}
}
调用顺序
- initApplicationEventMulticaster
- onRefresh
- registerListeners
- finishBeanFactoryInitialization
- EventListenerMethodProcessor.afterSingletonsInstantiated
- finishRefresh
此时 EventMulticaster 已经被初始化了,addListener 直接添加到 EventMulticaster,这种很晚的添加 listener 可能造成有些事件没有监听到。可能也是这种情况,SpringBoot 在 BootstrapContext 启动时有些 Listener 是使用 SPI 机制处理的。
Spring 的事件
正常启动执行顺序大概是这样的
ApplicationStartingEvent
ApplicationEnvironmentPreparedEvent
ApplicationContextInitializedEvent
ApplicationPreparedEvent
- initApplicationEventMulticaster
- onRefresh
- registerListeners
- finishBeanFactoryInitialization
- EventListenerMethodProcessor
- finishRefresh
ServletWebServerInitializedEvent
ContextRefreshedEvent
ApplicationStartedEvent
ApplicationReadyEvent
ServletWebServerInitializedEvent 和 SmartLifecycle.start 的顺序
参考:springboot之WebServerInitializedEvent事件
ServletWebServerInitializedEvent 在 AbstractApplicationContext#finishRefresh
at org.springframework.boot.web.servlet.context.ServletWebServerInitializedEvent.<init>(ServletWebServerInitializedEvent.java:40)
【这里publishEvent】at org.springframework.boot.web.servlet.context.WebServerStartStopLifecycle.start(WebServerStartStopLifecycle.java:45)
at org.springframework.context.support.DefaultLifecycleProcessor.doStart(DefaultLifecycleProcessor.java:178)
at org.springframework.context.support.DefaultLifecycleProcessor.access$200(DefaultLifecycleProcessor.java:54)
at org.springframework.context.support.DefaultLifecycleProcessor$LifecycleGroup.start(DefaultLifecycleProcessor.java:356)
at org.springframework.context.support.DefaultLifecycleProcessor$$Lambda$1360.1817920610.accept(Unknown Source:-1)
at java.lang.Iterable.forEach(Iterable.java:75)
at org.springframework.context.support.DefaultLifecycleProcessor.startBeans(DefaultLifecycleProcessor.java:155)
at org.springframework.context.support.DefaultLifecycleProcessor.onRefresh(DefaultLifecycleProcessor.java:123)
at org.springframework.context.support.AbstractApplicationContext.finishRefresh(AbstractApplicationContext.java:937)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:586)
AbstractApplicationContext#finishRefresh
// Initialize lifecycle processor for this context.
initLifecycleProcessor();
// Propagate refresh to lifecycle processor first.
// 【这里】
getLifecycleProcessor().onRefresh();
// Publish the final event.
publishEvent(new ContextRefreshedEvent(this));
实际上 ServletWebServerInitializedEvent 是在 WebServerStartStopLifecycle(implements SmartLifecycle)start 后启动 webServer 然后发布事件,于是有时候(有可能?) ServletWebServerInitializedEvent 顺序和自定义 SmartLifecycle.start 执行顺序可能乱序
mica 的 Listener
@AutoConfiguration
public class StartedEventListener {
@Async
@Order(Ordered.LOWEST_PRECEDENCE - 1)
@EventListener(WebServerInitializedEvent.class)
public void afterStart(WebServerInitializedEvent event) {
WebServerApplicationContext context = event.getApplicationContext();
Environment environment = context.getEnvironment();
String appName = environment.getRequiredProperty(MicaConstant.SPRING_APP_NAME_KEY);
int localPort = event.getWebServer().getPort();
String profile = StringUtils.arrayToCommaDelimitedString(environment.getActiveProfiles());
System.err.printf("---[%s]---启动完成,当前使用的端口:[%d],环境变量:[%s]---%n", appName, localPort, profile);
// 如果有 swagger,打印开发阶段的 swagger ui 地址
if (hasOpenApi()) {
System.out.printf("http://localhost:%s/doc.html%n", localPort);
System.out.printf("http://localhost:%s/swagger-ui/index.html%n", localPort);
} else {
System.out.printf("http://localhost:%s%n", localPort);
}
// linux 上将全部的 System.err 和 System.out 替换为log
if (SystemUtil.isLinux()) {
System.setOut(LogPrintStream.log(false));
// 去除 error 的转换,因为 error 会打印成很 N 条
// System.setErr(LogPrintStream.log(true));
}
}
private static boolean hasOpenApi() {
return Stream.of("springfox.documentation.spring.web.plugins.Docket", "io.swagger.v3.oas.models.OpenAPI")
.anyMatch(clazz -> ClassUtils.isPresent(clazz, null));
}
}