likes
comments
collection
share

Spring 事件机制源码分析

作者站长头像
站长
· 阅读数 27

定义

Spring时间是基于观察者模式拓展的。

各种角色

  • ApplicationEvent :表示Spring中的事件主体

  • ApplicationListener:事件监听器

  • 事件发布器

    • ApplicationEventPublisher
    • ApplicationEventMulticaster

源码分析

Spring在一初始化就有的Bean定义信息

Spring 事件机制源码分析 关于事件的有

  • [org.springframework.context.event.DefaultEventListenerFactory]
  • [org.springframework.context.event.EventListenerMethodProcessor]

通过继承接口ApplicationListener的分析

@Component
public class MyListener implements ApplicationListener<ApplicationContextEvent> {
    public  MyListener(){
        System.out.println("MyListener被创建");
    }

    @Override
    public void onApplicationEvent(ApplicationContextEvent event) {
        System.out.println("收到事件:" + event);
    }
}

在容器刷新十二大步的finishRefresh发布事件

核心代码在SimpleApplicationEventMulticaster中的multicastEvent

@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); // 在这里进行派发事件
       }
    }
}

可以定义线程池,进行多线程派发

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);
    }
}

spring怎么解析出的listener

何时调用:initializeBean时机

在ApplicationListenerDetector后置处理器中。


@Override
public Object postProcessAfterInitialization(Object bean, String beanName) {
    if (bean instanceof ApplicationListener) {
       // potentially not detected as a listener by getBeanNamesForType retrieval
       Boolean flag = this.singletonNames.get(beanName);
       if (Boolean.TRUE.equals(flag)) {
          // singleton bean (top-level or inner): register on the fly 加进去
          this .applicationContext.addApplicationListener((ApplicationListener<?>) bean);
       }
       else if (Boolean.FALSE.equals(flag)) {
          if (logger.isWarnEnabled() && !this.applicationContext.containsBean(beanName)) {
             // inner bean with other scope - can't reliably process events
             logger.warn("Inner bean '" + beanName + "' implements ApplicationListener interface " +
                   "but is not reachable for event multicasting by its containing ApplicationContext " +
                   "because it does not have singleton scope. Only top-level listener beans are allowed " +
                   "to be of non-singleton scope.");
          }
          this.singletonNames.remove(beanName);
       }
    }
    return bean;
}

注解模式

在注释中提到了一个类EventListenerMethodProcessor

是在所有bean初始化完之后的后置处理器(SmartInitializingSingleton.afterSingletonsInstantiated)


@Override
public void afterSingletonsInstantiated() {
    ConfigurableListableBeanFactory beanFactory = this.beanFactory;
    Assert.state(this.beanFactory != null, "No ConfigurableListableBeanFactory set");
    String[] beanNames = beanFactory.getBeanNamesForType(Object.class);
    for (String beanName : beanNames) {
       if (!ScopedProxyUtils.isScopedTarget(beanName)) {
          Class<?> type = null;
          try {
             type = AutoProxyUtils.determineTargetClass(beanFactory, beanName);
          }
          catch (Throwable ex) {
             // An unresolvable bean type, probably from a lazy bean - let's ignore it.
             if (logger.isDebugEnabled()) {
                logger.debug("Could not resolve target class for bean with name '" + beanName + "'", ex);
             }
          }
          if (type != null) {
             if (ScopedObject.class.isAssignableFrom(type)) {
                try {
                   Class<?> targetClass = AutoProxyUtils.determineTargetClass(
                         beanFactory, ScopedProxyUtils.getTargetBeanName(beanName));
                   if (targetClass != null) {
                      type = targetClass;
                   }
                }
                catch (Throwable ex) {
                   // An invalid scoped proxy arrangement - let's ignore it.
                   if (logger.isDebugEnabled()) {
                      logger.debug("Could not resolve target bean for scoped proxy '" + beanName + "'", ex);
                   }
                }
             }
             try {
               processBean(beanName, type); //处理Bean
             }
             catch (Throwable ex) {
                throw new BeanInitializationException("Failed to process @EventListener " +
                      "annotation on bean with name '" + beanName + "': " + ex.getMessage(), ex);
             }
          }
       }
    }
}

下面是利用反射机制找出对应Bean的方法创建ApplicationListenerMethodAdapter对象

是利用Spring一开始就有的DefaultEventListenerFactory进行创建,并使用了工厂+适配器模式

private void processBean(final String beanName, final Class<?> targetType) {
    if (!this.nonAnnotatedClasses.contains(targetType) &&
    //看你有没有注解
          AnnotationUtils.isCandidateClass(targetType, EventListener.class) &&
          !isSpringContainerClass(targetType)) {

       Map<Method, EventListener> annotatedMethods = null;
       try {
          annotatedMethods = MethodIntrospector.selectMethods(targetType,
                (MethodIntrospector.MetadataLookup<EventListener>) method ->
                      AnnotatedElementUtils.findMergedAnnotation(method, EventListener.class));
       }
       catch (Throwable ex) {
          // An unresolvable type in a method signature, probably from a lazy bean - let's ignore it.
          if (logger.isDebugEnabled()) {
             logger.debug("Could not resolve methods for bean with name '" + beanName + "'", ex);
          }
       }

       if (CollectionUtils.isEmpty(annotatedMethods)) {
          this.nonAnnotatedClasses.add(targetType);
          if (logger.isTraceEnabled()) {
             logger.trace("No @EventListener annotations found on bean class: " + targetType.getName());
          }
       }
       else {
          // Non-empty set of methods
          ConfigurableApplicationContext context = this.applicationContext;
          Assert.state(context != null, "No ApplicationContext set");
          List<EventListenerFactory> factories = this.eventListenerFactories;
          Assert.state(factories != null, "EventListenerFactory List not initialized");
          for (Method method : annotatedMethods.keySet()) {
             for (EventListenerFactory factory : factories) {//找出工厂 就是Spring一开始就加进去的
                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;
                }
             }
          }
          if (logger.isDebugEnabled()) {
             logger.debug(annotatedMethods.size() + " @EventListener methods processed on bean '" +
                   beanName + "': " + annotatedMethods);
          }
       }
    }
}

在适配器中利用bean的名字在ioc容器中获取对象,直接调用

转载自:https://juejin.cn/post/7377561821219946496
评论
请登录