• 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);
              }
           }
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    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; //所有增强器转好拦截器
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    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
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    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);
       }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    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();
       }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    然后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
    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;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    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;
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    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);
              }
           }
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45

    在这里插入图片描述

    在前面创建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);
              }
           }
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    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);
           }
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29

    在这里插入图片描述

    上面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);
          }
       }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

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

    在这里插入图片描述

    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()+";已进行处理....");
       }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    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);
       }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    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 +
                '}';
       }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    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 +
                '}';
       }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    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..."));
       }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29

    在还未进行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);
                    }
                 }
              }
           }
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43

    我们在这里打上条件断点

    在这里插入图片描述

    在这里插入图片描述

    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);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    为啥要创建这样一个适配器呢?虽然我们的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);
              }
           }
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    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;
    			}
    		}
    	}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
  • 相关阅读:
    【ruoyi】微服务关闭登录验证码
    [SpringCloud] Eureka 与 Ribbon 简介
    python 动态导入模块,实现模块热更新
    9.29 校招 实习 内推 面经
    炒鸡清晰的防御综合实验(内含区域划分,安全策略,用户认证,NAT认证,智能选路,域名访问)
    基于C语言的LogoCompiler的设计和原理
    Vue-04-axios异步通信
    Oracle转Poatgresql,ora2pg工具安装使用
    创新案例分享 | 建立校园大数据治理评价平台,高效提高教学效率与质量
    SparkSQL系列-7、自定义UDF函数?
  • 原文地址:https://blog.csdn.net/Youth_lql/article/details/126735162