mirror of
https://github.com/youthlql/JavaYouth.git
synced 2026-03-13 21:33:42 +08:00
1074 lines
35 KiB
Markdown
1074 lines
35 KiB
Markdown
---
|
||
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. 等以后真正的事件来了之后派发给ApplicationListenerMethodAdapter,ApplicationListenerMethodAdapter再用之前保存的信息反射调用实际的方法
|
||
|
||
|
||
|
||
最后就是三个方法,三个适配器
|
||
|
||
<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;
|
||
}
|
||
}
|
||
}
|
||
```
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|