Spring源码系列-第7章-AOP的执行流程原理和监听器原理

第7章-AOP的执行流程原理和监听器原理

文章目录

  1. 文章优先发布在Github,其它平台会晚一段时间,文章纠错与更新内容只在Github:https://github.com/youthlql/JavaYouth
  2. 转载须知:转载请注明GitHub出处,让我们一起维护一个良好的技术创作环境。
  3. 如果你要提交 issue 或者 pr 的话建议到 Github 提交。笔者会陆续更新,如果对你有所帮助,不妨Github点个Star~。你的Star是我创作的动力。

         

流程图-AOP运行流程原理

在这里插入图片描述

由Aop的执行流程引出方法拦截器

创建完代理对象之后,怎么执行的呢?

断点打到这里,F7进入方法

在这里插入图片描述

自然而然的跳到了cglib这里

在这里插入图片描述

CglibAopProxy#intercept()
    public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
       Object oldProxy = null;
       boolean setProxyContext = false;
       Object target = null;
       TargetSource targetSource = this.advised.getTargetSource();
       try {
          if (this.advised.exposeProxy) {
             // Make invocation available if necessary.
             oldProxy = AopContext.setCurrentProxy(proxy);
             setProxyContext = true;
          }
          // Get as late as possible to minimize the time we "own" the target, in case it comes from a pool...
          target = targetSource.getTarget();
          Class<?> targetClass = (target != null ? target.getClass() : null);
          List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
          Object retVal;
          // Check whether we only have one InvokerInterceptor: that is,
          // no real advice, but just reflective invocation of the target.
          if (chain.isEmpty() && Modifier.isPublic(method.getModifiers())) {
             Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
             retVal = methodProxy.invoke(target, argsToUse);
          }
          else {
             // We need to create a method invocation...
             retVal = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed();
          }
          retVal = processReturnType(proxy, target, method, retVal);
          return retVal;
       }
       finally {
          if (target != null && !targetSource.isStatic()) {
             targetSource.releaseTarget(target);
          }
          if (setProxyContext) {
             // Restore old proxy.
             AopContext.setCurrentProxy(oldProxy);
          }
       }
    }
CglibAopProxy#getInterceptorsAndDynamicInterceptionAdvice()

在这里插入图片描述

  1. 把5个增强器变成了方法拦截器,增强器只是保存信息的,真正执行还得靠方法拦截器。
  2. 我们再给上面的470行打上断点,看下之前是如何生成方法拦截器的。因为第一次生成的时候没有缓存,肯定能进去470行。

如何生成的方法拦截器?

Debug调用栈

在这里插入图片描述

在这里插入图片描述

可以看到就是在之前创建代理对象的时候增强器转成的拦截器

DefaultAdvisorChainFactory#getInterceptorsAndDynamicInterceptionAdvice()开始将增强器转为方法拦截器
    public List<Object> getInterceptorsAndDynamicInterceptionAdvice(
          Advised config, Method method, @Nullable Class<?> targetClass) {

       // This is somewhat tricky... We have to process introductions first,
       // but we need to preserve order in the ultimate list.
       AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance();
       Advisor[] advisors = config.getAdvisors();
       List<Object> interceptorList = new ArrayList<>(advisors.length);
       Class<?> actualClass = (targetClass != null ? targetClass : method.getDeclaringClass());
       Boolean hasIntroductions = null;

       for (Advisor advisor : advisors) {
          if (advisor instanceof PointcutAdvisor) {
             // Add it conditionally.
             PointcutAdvisor pointcutAdvisor = (PointcutAdvisor) advisor;
             if (config.isPreFiltered() || pointcutAdvisor.getPointcut().getClassFilter().matches(actualClass)) {
                MethodMatcher mm = pointcutAdvisor.getPointcut().getMethodMatcher();
                boolean match;
                if (mm instanceof IntroductionAwareMethodMatcher) {
                   if (hasIntroductions == null) {
                      hasIntroductions = hasMatchingIntroductions(advisors, actualClass);
                   }
                   match = ((IntroductionAwareMethodMatcher) mm).matches(method, actualClass, hasIntroductions);
                }
                else {
                   match = mm.matches(method, actualClass);
                }
                if (match) {
                   MethodInterceptor[] interceptors = registry.getInterceptors(advisor);//(如果是通知方法)把增强器转拦截器
                   if (mm.isRuntime()) {
                      // Creating a new object instance in the getInterceptors() method
                      // isn't a problem as we normally cache created chains.
                      for (MethodInterceptor interceptor : interceptors) {
                         interceptorList.add(new InterceptorAndDynamicMethodMatcher(interceptor, mm));
                      }
                   }
                   else {
                      interceptorList.addAll(Arrays.asList(interceptors));
                   }
                }
             }
          }
          else if (advisor instanceof IntroductionAdvisor) {
             IntroductionAdvisor ia = (IntroductionAdvisor) advisor;
             if (config.isPreFiltered() || ia.getClassFilter().matches(actualClass)) {
                Interceptor[] interceptors = registry.getInterceptors(advisor);
                interceptorList.addAll(Arrays.asList(interceptors));
             }
          }
          else {
             Interceptor[] interceptors = registry.getInterceptors(advisor);
             interceptorList.addAll(Arrays.asList(interceptors));
          }
       }

       return interceptorList; //所有增强器转好拦截器
    }
DefaultAdvisorAdapterRegistry#getInterceptors()
    private final List<AdvisorAdapter> adapters = new ArrayList<>(3);

	public MethodInterceptor[] getInterceptors(Advisor advisor) throws UnknownAdviceTypeException {
       List<MethodInterceptor> interceptors = new ArrayList<>(3);
       Advice advice = advisor.getAdvice();
       if (advice instanceof MethodInterceptor) {
          interceptors.add((MethodInterceptor) advice);
       }
       for (AdvisorAdapter adapter : this.adapters) {
          if (adapter.supportsAdvice(advice)) { //这里应该是一个适配器模式
             interceptors.add(adapter.getInterceptor(advisor)); 
          }
       }
       if (interceptors.isEmpty()) {
          throw new UnknownAdviceTypeException(advisor.getAdvice());
       }
       return interceptors.toArray(new MethodInterceptor[0]);
    }
  1. 增强器只是保存了哪些方法是通知方法的详细信息
  2. 拦截器里写了反射执行通知方法的逻辑,具体执行还得要方法拦截器
MethodBeforeAdviceAdapter适配器模式将增强器适配成方法拦截器

适配器模式适配一下

class MethodBeforeAdviceAdapter implements AdvisorAdapter, Serializable {

   @Override
   public boolean supportsAdvice(Advice advice) {
      return (advice instanceof MethodBeforeAdvice);
   }

   @Override
   public MethodInterceptor getInterceptor(Advisor advisor) {
      MethodBeforeAdvice advice = (MethodBeforeAdvice) advisor.getAdvice();
      return new MethodBeforeAdviceInterceptor(advice);
   }

}
MethodBeforeAdviceInterceptor
public class MethodBeforeAdviceInterceptor implements MethodInterceptor, BeforeAdvice, Serializable {

   private final MethodBeforeAdvice advice;


   /**
    * Create a new MethodBeforeAdviceInterceptor for the given advice.
    * @param advice the MethodBeforeAdvice to wrap
    */
   public MethodBeforeAdviceInterceptor(MethodBeforeAdvice advice) {
      Assert.notNull(advice, "Advice must not be null");
      this.advice = advice;
   }


   @Override
   @Nullable
   public Object invoke(MethodInvocation mi) throws Throwable { //invoke真正执行
      this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis());
      return mi.proceed();
   }

}

然后debug回到accept()方法

在这里插入图片描述

正式开始分析AOP运行流程-链式执行

在这里插入图片描述

  1. F7进入方法,上面讲过会调用CglibAopProxy内部类的DynamicAdvisedInterceptor#intercept()。这次我们来说下为什么会跳到DynamicAdvisedInterceptor#intercept()方法
  2. HelloService是一个代理对象,它的AOP代理是一个DynamicAdvisedInterceptor对象

在这里插入图片描述

  1. 而DynamicAdvisedInterceptor实现了MethodInterceptor接口
private static class DynamicAdvisedInterceptor implements MethodInterceptor, Serializable{...}
  1. cglib代理就是,当你调用方法的时候,真正会调用到实现了MethodInterceptor接口的DynamicAdvisedInterceptor#intercept()
  2. 至于具体的cglib原理,可以自己百度下。下面就看看intercept()的逻辑

注意有两个MethodInterceptor,包名不一样

package org.springframework.cglib.proxy;

import java.lang.reflect.Method;

public interface MethodInterceptor extends Callback {
    Object intercept(Object var1, Method var2, Object[] var3, MethodProxy var4) throws Throwable;
}
package org.aopalliance.intercept; //Spring定义的AOP规范接口

import javax.annotation.Nonnull;
import javax.annotation.Nullable;

@FunctionalInterface
public interface MethodInterceptor extends Interceptor {

   @Nullable
   Object invoke(@Nonnull MethodInvocation invocation) throws Throwable;

}

DynamicAdvisedInterceptor#intercept()

有intercept的是cglib的MethodInterceptor接口

    @Nullable //回调方法
    public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
       Object oldProxy = null;
       boolean setProxyContext = false;
       Object target = null;
       // 这里面有最原生的HelloService对象
       TargetSource targetSource = this.advised.getTargetSource();
       try {  //使用了代理对象就有增强功能
          if (this.advised.exposeProxy) { //使用ThreadLocal线程共享这个代理对象;
             // Make invocation available if necessary.
             oldProxy = AopContext.setCurrentProxy(proxy);
             setProxyContext = true;
          }
          // Get as late as possible to minimize the time we "own" the target, in case it comes from a pool...
          target = targetSource.getTarget();
          Class<?> targetClass = (target != null ? target.getClass() : null);
          List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
          Object retVal;  //chain是AOP后置处理器在第一次的时候就生成好的5个增强器,然后封装成的MethodInterceptor
          // Check whether we only have one InvokerInterceptor: that is,
          // no real advice, but just reflective invocation of the target.
          if (chain.isEmpty() && Modifier.isPublic(method.getModifiers())) {
             // We can skip creating a MethodInvocation: just invoke the target directly.
             // Note that the final invoker must be an InvokerInterceptor, so we know
             // it does nothing but a reflective operation on the target, and no hot
             // swapping or fancy proxying.
             Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
             retVal = methodProxy.invoke(target, argsToUse);
          }
          else { //CglibMethodInvocation【FilterChain(维护索引)】,5个MethodInterceptor就是Filter
             //创建一个方法执行的东西(拦截器链在此执行) We need to create a method invocation...
             retVal = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed();
          }
          retVal = processReturnType(proxy, target, method, retVal);
          return retVal;
       }
       finally {
          if (target != null && !targetSource.isStatic()) {
             targetSource.releaseTarget(target);
          }
          if (setProxyContext) {
             // Restore old proxy.
             AopContext.setCurrentProxy(oldProxy);
          }
       }
    }

在这里插入图片描述

在前面创建HelloService代理对象时创建好的方法拦截器,然后调用proceed()

在这里插入图片描述

CglibMethodInvocation#proceed()

在这里插入图片描述

顾名思义,就是用来执行Cglib生成的代理对象的方法

在这里插入图片描述

CglibAopProxy#proceed()

在这里插入图片描述

    public Object proceed() throws Throwable {
       try {
          return super.proceed(); //调用父类的方法
       }
       catch (RuntimeException ex) {
          throw ex;
       }
       catch (Exception ex) {
          if (ReflectionUtils.declaresException(getMethod(), ex.getClass()) ||
                KotlinDetector.isKotlinType(getMethod().getDeclaringClass())) {
             // Propagate original exception if declared on the target method
             // (with callers expecting it). Always propagate it for Kotlin code
             // since checked exceptions do not have to be explicitly declared there.
             throw ex;
          }
          else {
             // Checked exception thrown in the interceptor but not declared on the
             // target method signature -> apply an UndeclaredThrowableException,
             // aligned with standard JDK dynamic proxy behavior.
             throw new UndeclaredThrowableException(ex);
          }
       }
    }
ReflectiveMethodInvocation#proceed()
    public Object proceed() throws Throwable {
       // 当前拦截器的索引有没有超过 拦截器总数量-1   We start with an index of -1 and increment early.
       if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
          return invokeJoinpoint();
       }

       Object interceptorOrInterceptionAdvice =
             this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
       if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
          // Evaluate dynamic method matcher here: static part will already have
          // been evaluated and found to match.
          InterceptorAndDynamicMethodMatcher dm =
                (InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;
          Class<?> targetClass = (this.targetClass != null ? this.targetClass : this.method.getDeclaringClass());
          if (dm.methodMatcher.matches(this.method, targetClass, this.arguments)) {
             return dm.interceptor.invoke(this);
          }
          else {
             // Dynamic matching failed.
             // Skip this interceptor and invoke the next in the chain.
             return proceed();
          }
       }
       else {
          // It's an interceptor, so we just invoke it: The pointcut will have
          // been evaluated statically before this object was constructed.
          return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
       }
    }

在这里插入图片描述

上面5个拦截器都继承了Spring的org.aopalliance.intercept.MethodInterceptor,和Cglib的MethodInterceptor没关系了

ExposeInvocationInterceptor第一个拦截器

获取第一个拦截器ExposeInvocationInterceptor

在这里插入图片描述

往下走,直接走到了这里,准备调用ExposeInvocationInterceptor的invoke()

在这里插入图片描述

在这里插入图片描述

CglibAopProxy#proceed()

在这里插入图片描述

public Object proceed() throws Throwable {
   try {
      return super.proceed(); //调用父类的方法
   }
   catch (RuntimeException ex) {
      throw ex;
   }
   catch (Exception ex) {
      if (ReflectionUtils.declaresException(getMethod(), ex.getClass()) ||
            KotlinDetector.isKotlinType(getMethod().getDeclaringClass())) {
         // Propagate original exception if declared on the target method
         // (with callers expecting it). Always propagate it for Kotlin code
         // since checked exceptions do not have to be explicitly declared there.
         throw ex;
      }
      else {
         // Checked exception thrown in the interceptor but not declared on the
         // target method signature -> apply an UndeclaredThrowableException,
         // aligned with standard JDK dynamic proxy behavior.
         throw new UndeclaredThrowableException(ex);
      }
   }
}

结果又调回了,很明显这是个递归调用

在这里插入图片描述

MethodBeforeAdviceInterceptor-前置通知

然后后面的调用逻辑和前面就一样了,如下

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

这个时候就先执行切面的before方法,前置通知就执行了

在这里插入图片描述

继续调父类的方法

在这里插入图片描述

AspectJAfterAdvice-后置通知

在这里插入图片描述

后置通知这里先不执行,先继续执行下面的方法拦截器链路,最后finally再执行后置通知

AfterReturningAdviceInterceptor-返回通知

在这里插入图片描述

  1. 先往下走,我们就继续
AspectJAfterThrowingAdvice-异常通知

在这里插入图片描述

继续往下发现索引要超了

真正执行sayhello()

在这里插入图片描述

在这里插入图片描述

放行之后看控制台,sayhello方法就打印了。并且到目前为止,只有前面说的前置通知执行了。

在这里插入图片描述

然后咱们就往后返,

—返回—
AspectJAfterThrowingAdvice-异常通知

在这里插入图片描述

咱们这里没异常,就继续返回了

AfterReturningAdviceInterceptor-返回通知

返回到这里,准备执行返回通知

在这里插入图片描述

放行之后的控制台

在这里插入图片描述

继续返回

AspectJAfterAdvice-后置通知

准备执行后置通知

在这里插入图片描述

放行finally之后的控制台

在这里插入图片描述

ExposeInvocationInterceptor

继续返回

在这里插入图片描述

CglibAopProxy$DynamicAdvisedInterceptor

在这里插入图片描述

最后over,回到刚开头说的那个地方

Spring杂项

监听器原理【事件原理】

测试类

AppEventListener
@Component
public class AppEventListener {

   public AppEventListener(){
      System.out.println("AppEventListener...");
   }

   @EventListener(MessageEvent.class) //监听事件
   public void listenMessage(MessageEvent event){
      System.out.println("Message事件到达..."+event+";已发送邮件....");
   }


   @EventListener(ChangeEvent.class)
   public void listenChange(ChangeEvent event){
      System.out.println("Change事件到达..."+event+";已同步状态....");
   }

   @EventListener(PayloadApplicationEvent.class) //感知任意对象事件的
   public void listenPayload(PayloadApplicationEvent<A> event){
      System.out.println("Payload事件到达..."+event.getPayload()+";已进行处理....");
   }

}
AppEventPublisher
@Component
public class AppEventPublisher implements ApplicationEventPublisherAware {

   ApplicationEventPublisher eventPublisher;
   public AppEventPublisher(){
      System.out.println("AppEventPublisher....");
   }

   @Override
   public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
      this.eventPublisher = applicationEventPublisher;
   }

   public void publish(ApplicationEvent applicationEvent){
      eventPublisher.publishEvent(applicationEvent);
   }

   public void publish(Object o){
      eventPublisher.publishEvent(o);
   }
}
ChangeEvent
/**
 * 事件需要实现序列化接口
 */
public class ChangeEvent extends ApplicationEvent implements Serializable {
   private static final long serialVersionUID = 0L;
   private String state;
   private ChangeEvent(Object source) {
      super(source);
   }

   public ChangeEvent(Object source,String state){
      super(source);
      this.state = state;
   }

   public String getState() {
      return state;
   }

   @Override
   public String toString() {
      return "ChangeEvent{" +
            "state='" + state + '\'' +
            ", source=" + source +
            '}';
   }
}
MessageEvent
/**
 * 事件需要实现序列化接口
 */
public class MessageEvent extends ApplicationEvent implements Serializable {
   private static final long serialVersionUID = 0L;

   public MessageEvent(String source) {
      super(source);
   }

   @Override
   public String toString() {
      return "MessageEvent{" +
            ", source=" + source +
            '}';
   }
}
AnnotationMainTest
package cn.imlql.spring;

/**
 * 注解版Spring的用法
 */
public class AnnotationMainTest {

   public static void main(String[] args) {

      ApplicationContext applicationContext =
            new AnnotationConfigApplicationContext(MainConfig.class);
      
       
	  // 下面两种使用方法都可以
//    applicationContext.publishEvent(new Object());
//    applicationContext.publishEvent(new ApplicationEvent() {
//       @Override
//       public String toString() {
//          return super.toString();
//       }
//    });

      //测试事件
      AppEventPublisher eventPublisher = applicationContext.getBean(AppEventPublisher.class);
      eventPublisher.publish(new A());
      eventPublisher.publish(new MessageEvent("hello,你好"));
      eventPublisher.publish(new ChangeEvent(eventPublisher,"sending..."));
   }
}

在还未进行refresh()十二大步刷新时,容器就已经有了这两事件相关的Bean定义信息了。

在这里插入图片描述

EventListenerMethodProcessor

继承树

在这里插入图片描述

  1. 我们看到实现了SmartInitializingSingleton和BeanFactoryPostProcessor
  2. BeanFactoryPostProcessor我们反复在说,就是工厂后置处理环节。EventListenerMethodProcessor实现了BeanFactoryPostProcessor,说明他在工厂后置处理环节会做事
  3. SmartInitializingSingleton我们虽然说的不多,但也说过几次,调用链路如下。说明它会在容器刷新12大步的最后一步做事,并且看代码位置是在所有Bean创建完成之后做事。

AbstractApplicationContext#refresh() ==> AbstractApplicationContext#finishBeanFactoryInitialization() ==> DefaultListableBeanFactory#preInstantiateSingletons()

在这里插入图片描述

怎么分析呢?还是老办法,给EventListenerMethodProcessor标注@Override的方法打上断点

Debug启动

在这里插入图片描述

果然是从工厂后置处理那里过来的

放行,继续往下走。果然SmartInitializingSingleton这里开始做事了

在这里插入图片描述

EventListenerMethodProcessor#afterSingletonsInstantiated()
    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); //主要是这里
                }
                catch (Throwable ex) {
                   throw new BeanInitializationException("Failed to process @EventListener " +
                         "annotation on bean with name '" + beanName + "'", ex);
                }
             }
          }
       }
    }

我们在这里打上条件断点

在这里插入图片描述

在这里插入图片描述

F7进入下面的方法

在这里插入图片描述

咱们发现是创建了一个适配器

在这里插入图片描述

public ApplicationListenerMethodAdapter(String beanName, Class<?> targetClass, Method method) {
   this.beanName = beanName;
   this.method = BridgeMethodResolver.findBridgedMethod(method);
   this.targetMethod = (!Proxy.isProxyClass(targetClass) ?
         AopUtils.getMostSpecificMethod(method, targetClass) : this.method);
   this.methodKey = new AnnotatedElementKey(this.targetMethod, targetClass);

   EventListener ann = AnnotatedElementUtils.findMergedAnnotation(this.targetMethod, EventListener.class);
   this.declaredEventTypes = resolveDeclaredEventTypes(method, ann);
   this.condition = (ann != null ? ann.condition() : null);
   this.order = resolveOrder(this.targetMethod);
}

为啥要创建这样一个适配器呢?虽然我们的AppEventListener不是监听器,它只是在方法里标注了监听注解,我们自己没有写监听器。但是咱们解析@EventListener注解之后,在这里生成的适配器却实现了EventListener,也就说明这个适配器就是个监听器。

在这里插入图片描述

继续往下放行

在这里插入图片描述

在这里插入图片描述

把适配器放到了事件多播器里

  1. 这个思想就是,咱们自己创建的AppEventListener不是监听器,只在方法里标了注解
  2. spring准备了另外一个类ApplicationListenerMethodAdapter,把你这个beanName和方法名等等信息封装到这里。然后放到事件多播器里
  3. 等以后真正的事件来了之后派发给ApplicationListenerMethodAdapter,ApplicationListenerMethodAdapter再用之前保存的信息反射调用实际的方法

最后就是三个方法,三个适配器

在这里插入图片描述

监听器如何感知到事件?

给下面的位置打上断点

在这里插入图片描述

在这里插入图片描述

AbstractApplicationContext#publishEvent()
    public void publishEvent(Object event) {
       publishEvent(event, null);
    }


    protected void publishEvent(Object event, @Nullable ResolvableType eventType) {
       Assert.notNull(event, "Event must not be null");

       // Decorate event as an ApplicationEvent if necessary
       ApplicationEvent applicationEvent;
       if (event instanceof ApplicationEvent) { // ApplicationEvent接口下的事件
          applicationEvent = (ApplicationEvent) event;
       }
       else {  //任意对象作为事件最终被封装到了 PayloadApplicationEvent
          applicationEvent = new PayloadApplicationEvent<>(this, event);
          if (eventType == null) {
             eventType = ((PayloadApplicationEvent<?>) applicationEvent).getResolvableType();
          }
       }

       // Multicast right now if possible - or lazily once the multicaster is initialized
       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);
          }
       }
    }
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) {  //使用观察者模式,把所有事件监听器拿来,调用他们的onApplicationEvent方法即可
             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);
		}
	}

	@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()) ||
					(event instanceof PayloadApplicationEvent &&
							matchesClassCastMessage(msg, ((PayloadApplicationEvent) event).getPayload().getClass()))) {
				// Possibly a lambda-defined listener which we could not resolve the generic event type for
				// -> let's suppress the exception.
				Log loggerToUse = this.lazyLogger;
				if (loggerToUse == null) {
					loggerToUse = LogFactory.getLog(getClass());
					this.lazyLogger = loggerToUse;
				}
				if (loggerToUse.isTraceEnabled()) {
					loggerToUse.trace("Non-matching event type for listener: " + listener, ex);
				}
			}
			else {
				throw ex;
			}
		}
	}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值