--- title: Spring源码系列-第7章-AOP的执行流程原理和监听器原理 tags: - Spring源码 categories: - Spring - 源码V1 keywords: Spring,框架,spring源码 description: AOP执行流程和监听器原理 cover: 'https://npm.elemecdn.com/lql_static@latest/logo/spring.png' abbrlink: fb3552e0 date: 2022-04-17 12:01:02 --- # 第7章-AOP的执行流程原理和监听器原理 ## 流程图-AOP运行流程原理 ## 由Aop的执行流程引出方法拦截器 ### 创建完代理对象之后,怎么执行的呢? 断点打到这里,F7进入方法 自然而然的跳到了cglib这里 #### CglibAopProxy#intercept() ```java 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 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()开始将增强器转为方法拦截器 ```java public List 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 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() ```java private final List adapters = new ArrayList<>(3); public MethodInterceptor[] getInterceptors(Advisor advisor) throws UnknownAdviceTypeException { List 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适配器模式将增强器适配成方法拦截器 适配器模式适配一下 ```java 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 ```java 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对象 3. 而DynamicAdvisedInterceptor实现了MethodInterceptor接口 ```java private static class DynamicAdvisedInterceptor implements MethodInterceptor, Serializable{...} ``` 4. cglib代理就是,当你调用方法的时候,真正会调用到实现了MethodInterceptor接口的DynamicAdvisedInterceptor#intercept() 5. **至于具体的cglib原理,可以自己百度下**。下面就看看intercept()的逻辑 注意有两个MethodInterceptor,包名不一样 ```java 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; } ``` ```java 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接口 ```java @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 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() ```java 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() ```java 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() ```java 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 ```java @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 event){ System.out.println("Payload事件到达..."+event.getPayload()+";已进行处理...."); } } ``` #### AppEventPublisher ```java @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 ```java /** * 事件需要实现序列化接口 */ 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 ```java /** * 事件需要实现序列化接口 */ 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 ```java 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() ```java 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进入下面的方法 咱们发现是创建了一个适配器 ```java 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() ```java 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() ```java //事件派发可以是异步 @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; } } } ```