diff --git a/.nojekyll b/.nojekyll deleted file mode 100644 index e69de29..0000000 diff --git a/README.md b/README.md index 9a7faac..3d3530f 100644 --- a/README.md +++ b/README.md @@ -140,7 +140,7 @@ -## 源码【03.19更新】 +## 源码【04.17更新】 @@ -156,6 +156,8 @@ [06.第6章-AOP的后置处理器和代理对象的创建](docs/spring-sourcecode-v1/06.第6章-AOP的后置处理器和代理对象的创建.md) +[07.第7章-AOP的执行流程原理和监听器原理](docs/spring-sourcecode-v1/07.第7章-AOP的执行流程原理和监听器原理.md) + # Netty ## 入门 diff --git a/_coverpage.md b/_coverpage.md deleted file mode 100644 index 28d1275..0000000 --- a/_coverpage.md +++ /dev/null @@ -1,13 +0,0 @@ -

- -

- - - -

JavaYouth

- -[我的博客](https://imlql.cn/) -[GitHub]() -[开始阅读](#Java) - - diff --git a/_navbar.md b/_navbar.md deleted file mode 100644 index 1daa917..0000000 --- a/_navbar.md +++ /dev/null @@ -1,4 +0,0 @@ -- [首页](https://imlql.cn/JavaYouth/#/) -- [Github](https://github.com/youthlql/JavaYouth) -- [博客](https://imlql.cn/) -- [CSDN](https://blog.csdn.net/Youth_lql) \ No newline at end of file diff --git a/docs/spring-sourcecode-v1/07.第7章-AOP的执行流程原理和监听器原理.md b/docs/spring-sourcecode-v1/07.第7章-AOP的执行流程原理和监听器原理.md new file mode 100644 index 0000000..39a9dbf --- /dev/null +++ b/docs/spring-sourcecode-v1/07.第7章-AOP的执行流程原理和监听器原理.md @@ -0,0 +1,1073 @@ +--- +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; + } + } + } +``` + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/index.html b/index.html deleted file mode 100644 index 26b7600..0000000 --- a/index.html +++ /dev/null @@ -1,43 +0,0 @@ - - - - - JavaYouth - - - - - - -
- - - - - - - - - - - - - - - -