监听器 && 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));
  }

}
posted @ 2023-12-01 21:31  YangDanMua  阅读(109)  评论(0编辑  收藏  举报