Files
JavaYouth/docs/spring-sourcecode-v1/07.第7章-AOP的执行流程原理和监听器原理.md
2022-07-24 20:30:09 +08:00

1074 lines
35 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
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运行流程原理
<img src="https://npm.elemecdn.com/youthlql@1.0.7/spring-sourcecode-v1/flow_chart/AOP%E8%BF%90%E8%A1%8C%E6%B5%81%E7%A8%8B%E5%8E%9F%E7%90%86.jpg">
## 由Aop的执行流程引出方法拦截器
### 创建完代理对象之后,怎么执行的呢?
断点打到这里F7进入方法
<img src="https://npm.elemecdn.com/youthlql@1.0.6/spring-sourcecode-v1/chapter_07/image-20211012195045643.png"/>
自然而然的跳到了cglib这里
<img src="https://npm.elemecdn.com/youthlql@1.0.6/spring-sourcecode-v1/chapter_07/image-20211012195313364.png" />
#### 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<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()
<img src="https://npm.elemecdn.com/youthlql@1.0.6/spring-sourcecode-v1/chapter_07/image-20211012195459849.png" />
1. 把5个增强器变成了方法拦截器增强器只是保存信息的真正执行还得靠方法拦截器。
2. 我们再给上面的470行打上断点看下之前是如何生成方法拦截器的。因为第一次生成的时候没有缓存肯定能进去470行。
### 如何生成的方法拦截器?
#### Debug调用栈
<img src="https://npm.elemecdn.com/youthlql@1.0.6/spring-sourcecode-v1/chapter_07/image-20211012201950845.png" />
<img src="https://npm.elemecdn.com/youthlql@1.0.6/spring-sourcecode-v1/chapter_07/image-20211012202049726.png" />
可以看到就是在之前创建代理对象的时候增强器转成的拦截器
#### DefaultAdvisorChainFactory#getInterceptorsAndDynamicInterceptionAdvice()开始将增强器转为方法拦截器
```java
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()
```java
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适配器模式将增强器适配成方法拦截器
适配器模式适配一下
```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()方法
<img src="https://npm.elemecdn.com/youthlql@1.0.6/spring-sourcecode-v1/chapter_07/image-20211012202236451.png" />
## 正式开始分析AOP运行流程-链式执行
<img src="https://npm.elemecdn.com/youthlql@1.0.6/spring-sourcecode-v1/chapter_07/image-20211012220057607.png"/>
1. F7进入方法上面讲过会调用CglibAopProxy内部类的DynamicAdvisedInterceptor#intercept()。这次我们来说下为什么会跳到DynamicAdvisedInterceptor#intercept()方法
2. HelloService是一个代理对象它的AOP代理是一个DynamicAdvisedInterceptor对象
<img src="https://npm.elemecdn.com/youthlql@1.0.6/spring-sourcecode-v1/chapter_07/image-20211012220839278.png"/>
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<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);
}
}
}
```
<img src="https://npm.elemecdn.com/youthlql@1.0.6/spring-sourcecode-v1/chapter_07/image-20211012223909994.png" />
在前面创建HelloService代理对象时创建好的方法拦截器然后调用proceed()
<img src="https://npm.elemecdn.com/youthlql@1.0.6/spring-sourcecode-v1/chapter_07/image-20211012224227624.png" />
### CglibMethodInvocation#proceed()
<img src="https://npm.elemecdn.com/youthlql@1.0.6/spring-sourcecode-v1/chapter_07/image-20211012224431389.png" />
顾名思义就是用来执行Cglib生成的代理对象的方法
<img src="https://npm.elemecdn.com/youthlql@1.0.6/spring-sourcecode-v1/chapter_07/image-20211012224629196.png"/>
#### CglibAopProxy#proceed()
<img src="https://npm.elemecdn.com/youthlql@1.0.6/spring-sourcecode-v1/chapter_07/image-20211012231748956.png" />
```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);
}
}
```
<img src="https://npm.elemecdn.com/youthlql@1.0.6/spring-sourcecode-v1/chapter_07/image-20211012225055742.png"/>
上面5个拦截器都继承了Spring的org.aopalliance.intercept.MethodInterceptor和Cglib的MethodInterceptor没关系了
#### ExposeInvocationInterceptor第一个拦截器
获取第一个拦截器ExposeInvocationInterceptor
<img src="https://npm.elemecdn.com/youthlql@1.0.6/spring-sourcecode-v1/chapter_07/image-20211012225804099.png"/>
往下走直接走到了这里准备调用ExposeInvocationInterceptor的invoke()
<img src="https://npm.elemecdn.com/youthlql@1.0.6/spring-sourcecode-v1/chapter_07/image-20211012230419970.png" />
<img src="https://npm.elemecdn.com/youthlql@1.0.6/spring-sourcecode-v1/chapter_07/image-20211012230646766.png"/>
##### CglibAopProxy#proceed()
<img src="https://npm.elemecdn.com/youthlql@1.0.6/spring-sourcecode-v1/chapter_07/image-20211012230842658.png" />
```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);
}
}
}
```
结果又调回了,很明显这是个递归调用
<img src="https://npm.elemecdn.com/youthlql@1.0.6/spring-sourcecode-v1/chapter_07/image-20211012230930440.png" />
#### MethodBeforeAdviceInterceptor-前置通知
然后后面的调用逻辑和前面就一样了,如下
<img src="https://npm.elemecdn.com/youthlql@1.0.6/spring-sourcecode-v1/chapter_07/image-20211012231135459.png" />
<img src="https://npm.elemecdn.com/youthlql@1.0.6/spring-sourcecode-v1/chapter_07/image-20211012231202337.png" />
<img src="https://npm.elemecdn.com/youthlql@1.0.6/spring-sourcecode-v1/chapter_07/image-20211012231327882.png"/>
这个时候就先执行切面的before方法前置通知就执行了
<img src="https://npm.elemecdn.com/youthlql@1.0.6/spring-sourcecode-v1/chapter_07/image-20211012232119227.png" />
继续调父类的方法
<img src="https://npm.elemecdn.com/youthlql@1.0.6/spring-sourcecode-v1/chapter_07/image-20211012231412866.png"/>
#### AspectJAfterAdvice-后置通知
<img src="https://npm.elemecdn.com/youthlql@1.0.6/spring-sourcecode-v1/chapter_07/image-20211012232315412.png" />
后置通知这里先不执行先继续执行下面的方法拦截器链路最后finally再执行后置通知
#### AfterReturningAdviceInterceptor-返回通知
<img src="https://npm.elemecdn.com/youthlql@1.0.6/spring-sourcecode-v1/chapter_07/image-20211012232551952.png" />
1. 先往下走,我们就继续
#### AspectJAfterThrowingAdvice-异常通知
<img src="https://npm.elemecdn.com/youthlql@1.0.6/spring-sourcecode-v1/chapter_07/image-20211012232910377.png"/>
继续往下发现索引要超了
#### 真正执行sayhello()
<img src="https://npm.elemecdn.com/youthlql@1.0.6/spring-sourcecode-v1/chapter_07/image-20211012233113154.png"/>
<img src="https://npm.elemecdn.com/youthlql@1.0.6/spring-sourcecode-v1/chapter_07/image-20211012233212466.png" />
放行之后看控制台sayhello方法就打印了。并且到目前为止只有前面说的前置通知执行了。
<img src="https://npm.elemecdn.com/youthlql@1.0.6/spring-sourcecode-v1/chapter_07/image-20211012233317479.png" />
然后咱们就往后返,
#### ---返回---
#### AspectJAfterThrowingAdvice-异常通知
<img src="https://npm.elemecdn.com/youthlql@1.0.6/spring-sourcecode-v1/chapter_07/image-20211012233506053.png" />
咱们这里没异常,就继续返回了
#### AfterReturningAdviceInterceptor-返回通知
返回到这里,准备执行返回通知
<img src="https://npm.elemecdn.com/youthlql@1.0.6/spring-sourcecode-v1/chapter_07/image-20211012233633239.png" />
放行之后的控制台
<img src="https://npm.elemecdn.com/youthlql@1.0.6/spring-sourcecode-v1/chapter_07/image-20211012233731212.png" />
继续返回
#### AspectJAfterAdvice-后置通知
准备执行后置通知
<img src="https://npm.elemecdn.com/youthlql@1.0.6/spring-sourcecode-v1/chapter_07/image-20211012233837744.png">
放行finally之后的控制台
<img src="https://npm.elemecdn.com/youthlql@1.0.6/spring-sourcecode-v1/chapter_07/image-20211012233944290.png" />
#### ExposeInvocationInterceptor
继续返回
<img src="https://npm.elemecdn.com/youthlql@1.0.6/spring-sourcecode-v1/chapter_07/image-20211012234108557.png" />
#### CglibAopProxy$DynamicAdvisedInterceptor
<img src="https://npm.elemecdn.com/youthlql@1.0.6/spring-sourcecode-v1/chapter_07/image-20211012234214735.png" />
最后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<A> 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定义信息了。
<img src="https://npm.elemecdn.com/youthlql@1.0.6/spring-sourcecode-v1/chapter_07/image-20211013162535782.png"/>
### EventListenerMethodProcessor
#### 继承树
<img src="https://npm.elemecdn.com/youthlql@1.0.6/spring-sourcecode-v1/chapter_07/image-20211013162805867.png" />
1. 我们看到实现了SmartInitializingSingleton和BeanFactoryPostProcessor
2. BeanFactoryPostProcessor我们反复在说就是工厂后置处理环节。EventListenerMethodProcessor实现了BeanFactoryPostProcessor说明他在工厂后置处理环节会做事
3. SmartInitializingSingleton我们虽然说的不多但也说过几次调用链路如下。说明它会在容器刷新12大步的最后一步做事并且看代码位置是在所有Bean创建完成之后做事。
> AbstractApplicationContext#refresh() ==> AbstractApplicationContext#finishBeanFactoryInitialization() ==> DefaultListableBeanFactory#preInstantiateSingletons()
<img src="https://npm.elemecdn.com/youthlql@1.0.6/spring-sourcecode-v1/chapter_07/image-20211013164017769.png" />
怎么分析呢还是老办法给EventListenerMethodProcessor标注@Override的方法打上断点
Debug启动
<img src="https://npm.elemecdn.com/youthlql@1.0.6/spring-sourcecode-v1/chapter_07/image-20211013170249700.png"/>
果然是从工厂后置处理那里过来的
放行继续往下走。果然SmartInitializingSingleton这里开始做事了
<img src="https://npm.elemecdn.com/youthlql@1.0.6/spring-sourcecode-v1/chapter_07/image-20211013170435169.png" />
#### 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);
}
}
}
}
}
```
我们在这里打上条件断点
<img src="https://npm.elemecdn.com/youthlql@1.0.6/spring-sourcecode-v1/chapter_07/image-20211013170852409.png"/>
<img src="https://npm.elemecdn.com/youthlql@1.0.6/spring-sourcecode-v1/chapter_07/image-20211013171247356.png" />
F7进入下面的方法
<img src="https://npm.elemecdn.com/youthlql@1.0.6/spring-sourcecode-v1/chapter_07/image-20211013171641031.png" />
咱们发现是创建了一个适配器
<img src="https://npm.elemecdn.com/youthlql@1.0.6/spring-sourcecode-v1/chapter_07/image-20211013171728867.png" />
```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也就说明这个适配器就是个监听器。
<img src="https://npm.elemecdn.com/youthlql@1.0.6/spring-sourcecode-v1/chapter_07/image-20211013171936784.png" />
继续往下放行
<img src="https://npm.elemecdn.com/youthlql@1.0.6/spring-sourcecode-v1/chapter_07/image-20211013172130892.png" />
<img src="https://npm.elemecdn.com/youthlql@1.0.6/spring-sourcecode-v1/chapter_07/image-20211013172239216.png" />
把适配器放到了事件多播器里
1. 这个思想就是咱们自己创建的AppEventListener不是监听器只在方法里标了注解
2. spring准备了另外一个类ApplicationListenerMethodAdapter把你这个beanName和方法名等等信息封装到这里。然后放到事件多播器里
3. 等以后真正的事件来了之后派发给ApplicationListenerMethodAdapterApplicationListenerMethodAdapter再用之前保存的信息反射调用实际的方法
最后就是三个方法,三个适配器
<img src="https://npm.elemecdn.com/youthlql@1.0.6/spring-sourcecode-v1/chapter_07/image-20211013172925798.png" />
#### 监听器如何感知到事件?
给下面的位置打上断点
<img src="https://npm.elemecdn.com/youthlql@1.0.6/spring-sourcecode-v1/chapter_07/image-20211013173037562.png" />
<img src="https://npm.elemecdn.com/youthlql@1.0.6/spring-sourcecode-v1/chapter_07/image-20211013173146059.png" />
##### 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;
}
}
}
```