Spring

AOP

Aop实现之AJC编译器

AJCaspectj-maven-plugin插件,它可以实现静态编译代理,编译阶段 compile 对文件进行增强,可以从 生成的.class 文件可以看出

导入AJC依赖

1
2
3
4
5
6
<!-- https://mvnrepository.com/artifact/org.aspectj/aspectjrt -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>1.8.13</version>
</dependency>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>aspectj-maven-plugin</artifactId>
<version>1.11</version>
<configuration>
<complianceLevel>1.8</complianceLevel>
<source>1.8</source>
<target>1.8</target>
<showWeaveInfo>true</showWeaveInfo>
<Xlint>ignore</Xlint>
<encoding>UTF-8</encoding>
<!-- 注意:IDEA下这个值要设置为false,否则运行程序时IDEA会再次编译,导致aspectj-maven-plugin编译的结果被覆盖 -->
<skip>false</skip>
</configuration>
<executions>
<execution>
<configuration>
<skip>false</skip>
</configuration>
<goals>
<goal>compile</goal>
</goals>
</execution>
</executions>
</plugin>
1
2
3
4
5
6
7
8
9
@Service
public class MyService {

private static final Logger logger = LoggerFactory.getLogger(MyService.class);

public void execute() {
logger.info("execute");
}
}
1
2
3
4
5
6
7
8
9
10
11
@Aspect
@Component
public class MyAspect {

private static final Logger logger = LoggerFactory.getLogger(MyAspect.class);

@Before("execution(* com.example.demo.service.MyService.execute())")
public void before() {
logger.info("before");
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
@SpringBootApplication
public class SpringAopApplication {

private static final Logger logger = LoggerFactory.getLogger(SpringAopApplication.class);

public static void main(String[] args) {

ConfigurableApplicationContext context = SpringApplication.run(SpringAopApplication.class, args);
MyService bean = context.getBean(MyService.class);

logger.info("service class:{}", bean.getClass());

bean.execute();

context.close();
}
}

image-20230710174653369

image-20230710174742615

Aop实现之agent类加载

1
2
3
4
5
6
7
8
9
10
11
12
13
14
@Service
public class MyService {

private static final Logger logger = LoggerFactory.getLogger(MyService.class);

public void execute() {
logger.info("execute");
submit();
}

public void submit() {
logger.info("submit");
}
}
1
2
3
4
5
6
7
8
9
10
11
@Aspect
@Component
public class MyAspect {

private static final Logger logger = LoggerFactory.getLogger(MyAspect.class);

@Before("execution(* com.example.demo.service.MyService.*())")
public void before() {
logger.info("before");
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
@SpringBootApplication
public class SpringAopApplication {

private static final Logger logger = LoggerFactory.getLogger(SpringAopApplication.class);

public static void main(String[] args) {

ConfigurableApplicationContext context = SpringApplication.run(SpringAopApplication.class, args);
MyService bean = context.getBean(MyService.class);

logger.info("service class:{}", bean.getClass());

bean.execute();

// context.close();
}
}

image-20230710225746667

我们发现间接调用的方法没有被增强,这是因为该方法的调用没有被容器代理,属于类中的this调用

使用agent类加载增强

image-20230710181639846

1
-javaagent:/Users/yuanjianwei/.m2/repository/org/aspectj/aspectjweaver/1.9.7/aspectjweaver-1.9.7.jar

image-20230710230024351

使用 Arthas 类加载时增强后的反编译该字节码文件,发现agrent在类加载时对非贬义字节码文件进行了织入增强

1
jad com.example.demo.service.MyService

image-20230710230248216

Aop实现之proxy

JDK

JDK代理实现

JDK 只能代理 实现接口的类

代理目标
1
2
3
4
public interface SmsService {

String send(String message);
}
1
2
3
4
5
6
7
8
9
10
11
public class SmsServiceImpl implements SmsService {

private static final Logger LOGGER = LoggerFactory.getLogger(SmsServiceImpl.class);

@Override
public String send(String message) {

LOGGER.info("send message:" + message);
return message;
}
}
代理类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public class DebugInvocationHandler implements InvocationHandler {

private static final Logger LOGGER = LoggerFactory.getLogger(SmsServiceImpl.class);

private final Object target;

public DebugInvocationHandler(Object target) {
this.target = target;
}

@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

LOGGER.info("before mothed:" + method.getName());

Object result = method.invoke(target, args);

LOGGER.info("after mothed:" + method.getName());

return result;
}
}
代理工厂

使用 Proxy.newProxyInstance 创建新的代理实例对象

1
Proxy.newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)
1
2
3
4
5
6
7
8
9
10
11
public class JdkProxyFactory {

public static Object getProxy(Object target) {

return Proxy.newProxyInstance(
target.getClass().getClassLoader(),
target.getClass().getInterfaces(),
new DebugInvocationHandler(target)
);
}
}
1
2
3
4
5
@Test
public void test() {
SmsService smsService = (SmsService) JdkProxyFactory.getProxy(new SmsServiceImpl());
smsService.send("Hello World!");
}

image-20230711174446761

简单版本

image-20230711175232131

JDK代理原理
模拟代理类实现

将 增强的内容 进行抽象

1
2
3
4
public interface MyInvocationHandler {

public Object invoke(Object proxy, Method method, Object[] args) throws Throwable;
}

将 增强的抽象方法 和 目标对象 作为成员变量注入

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
public class $Proxy implements SmsService {

private MyInvocationHandler myInvocationHandler;

private final Object target;

public $Proxy(MyInvocationHandler myInvocationHandler, Object target) {
this.myInvocationHandler = myInvocationHandler;
this.target = target;
}

@Override
public String send(String message) {
try {
return (String) myInvocationHandler.invoke(
this,
target.getClass().getMethod(
new Object() {}.getClass().getEnclosingMethod().getName(),
new Object() {}.getClass().getEnclosingMethod().getParameterTypes()
),
new Object[]{message}
);
// 捕获运行时异常 直接抛出
} catch (RuntimeException | Error e) {
throw e;
// 捕获检查异常 将 检查异常 转换为 运行异常
} catch (Throwable e) {
throw new UndeclaredThrowableException(e);
}
}
}

通过 构造方法 获取对象,调用方法实现 功能增强

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
@Test
public void test$Proxy() {

SmsServiceImpl smsService = new SmsServiceImpl();

$Proxy $Proxy = new $Proxy(
(proxy, method, args) -> {
log.info("before mothed:" + method.getName());
Object result = method.invoke(smsService, args);
log.info("after mothed:" + method.getName());
return result;
},
smsService
);

$Proxy.send("Hello World!");
}

image-20230715155151821

JDK代理源码

对于 字节码 进行 反编译

image-20230715213522700

image-20230715213537939

JDK代理字节码生成

JDK 代理类的生成直接是通过ASM生成字节码,没有通过对于Java源码(.class文件)的编译。通过对于字节码的反编译可以看到 Java源码。

ASM的作用是运行时动态生成字节码,没有对 源码的编译阶段。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
@Test
public void testAsm() throws Exception {

// 获取 类字节码
byte[] dump = $ProxyASMDump.dump();

// 构造类加载起
ClassLoader classLoader = new ClassLoader() {
@Override
protected Class<?> findClass(String name) throws ClassNotFoundException {
return super.defineClass(name, dump, 0, dump.length);
}
};
// 使用 指定类加载器的二进制名称 加载类
Class<?> proxy = classLoader.loadClass("com.example.demo.$ProxyASM");

// 获取 指定参数的构造方法
Constructor<?> constructor = proxy.getConstructor(InvocationHandler.class);

// 调用 构造方法 构造 代理实例
SmsService smsService = (SmsService) constructor.newInstance(new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
log.info("before mothed:" + method.getName());
Object result = method.invoke(new SmsServiceImpl(), args);
log.info("after mothed:" + method.getName());
return result;
}
});

// 调用代理对象进行方法增强
smsService.send("Hello Wolrd!");
}

Cglib

Cglib代理实现
1
2
3
4
5
6
7
8
9
10
11
@Service
public class SmsService {

private static final Logger logger = LoggerFactory.getLogger(SmsService.class);

public String send(String message) {

logger.info("send message:" + message);
return message;
}
}

通过 Enhancer.create 创建代理类,两个参数:第一个是 Class type 即目标代理类,第二个是 Callback callback,第二个参数我们自定义 Callback 的子类 MethodInterceptor 并重写 intercept 方法,intercept 用于拦截增强被代理类的方法

1
2
3
4
5
6
7
8
9
10
11
12
13
@Test
public void test() {

SmsService smsService = (SmsService) Enhancer.create(
SmsService.class,
(MethodInterceptor) (o, method, objects, methodProxy) -> {
log.info("before mothed:" + method.getName());
Object result = method.invoke(new SmsService(), objects);
log.info("after mothed:" + method.getName());
return result;
});
smsService.send("Hello world!");
}

image-20230714145641123

Gglib 代理的本质是 方法的重写 ,目标代理类是父类型,代理类是子类型,所以父类型的目标方法不能被 final 修饰

代理优化
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public class DebugMethodInterceptor implements MethodInterceptor {

private final static Logger logger = LoggerFactory.getLogger(DebugMethodInterceptor.class);

/**
* @param obj 被代理的对象即需要增强的对象
* @param method 被拦截的方法即需要增强的方法
* @param args 方法入参
* @param proxy 用于调用原始的方法
* @return
* @throws Throwable
*/
@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {

logger.info("before mothed:" + method.getName());
// MethodProxy 内部避免通过 反射 调用
// invokeSuper 第一个参数:代理对象,第二个:代理方法执行参数
Object result = proxy.invokeSuper(obj, args);
logger.info("after mothed:" + method.getName());
return result;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class CglibProxyFactory {

public static Object getProxy(Class<?> clazz) {
// 设置动态代理增强类
Enhancer enhancer = new Enhancer();
// 设置类加载器
enhancer.setClassLoader(clazz.getClassLoader());
// 设置被代理类
enhancer.setSuperclass(clazz);
// 设置方法拦截器
enhancer.setCallback(new DebugMethodInterceptor());
// 创建代理类
return enhancer.create();
}
}
1
2
3
4
5
6
7
@Test
public void testProxy() {

SmsService proxy = (SmsService) CglibProxyFactory.getProxy(SmsService.class);

proxy.send("Hello World!");
}
Cglib代理原理

Cglib 代理类 的本质是继承 代理目标类,并 重写代理方法 对 代理方法进行增强。

通过 实现 MethodInterceptor 接口方法,

image-20230716041405655

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
public class ProxyService extends SmsService {

private MethodInterceptor methodInterceptor;

private static final Method method;

static {
try {
method = SmsService.class.getDeclaredMethod("send", String.class);
} catch (NoSuchMethodException e) {
throw new RuntimeException(e);
}
}

public ProxyService(MethodInterceptor methodInterceptor) {
this.methodInterceptor = methodInterceptor;
}

@Override
public String send(String message) {
try {
return (String) methodInterceptor.intercept(
this,
method,
new Object[]{message},
null
);
} catch (Throwable e) {
throw new RuntimeException(e);
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@Test
public void test$Proxy() {
SmsService smsService = new SmsService();

ProxyService proxyService = new ProxyService(
(obj, method, args, proxy) -> {
log.info("before mothed:" + method.getName());
Object result = method.invoke(smsService, args);
log.info("after mothed:" + method.getName());
return result;
}
);

proxyService.send("Hello World!");
}

image-20230716035340730

Cglib MethodProxy

MethodInterceptor 接口中的回调的方法有一个 MethodProxy,可以避免通过反射调用被代理的方法而是直接调用

新增一个方法调用父类的原始方法 super.send()作为本来的原始功能方法,使用 MethodProxy.create() 进行创建 MethodProxy 方法代理对象

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
public class ProxyService extends SmsService {

private MethodInterceptor methodInterceptor;

private static final Method method;

// 方法代理对象
private static final MethodProxy methodProxy;

static {
try {
method = SmsService.class.getDeclaredMethod("send", String.class);
// 使用 MethodProxy.create() 进行创建
methodProxy = MethodProxy.create(
SmsService.class,
ProxyService.class,
"(Ljava/lang/String;)Ljava/lang/String;",
"send",
"superSend"
);
} catch (NoSuchMethodException e) {
throw new RuntimeException(e);
}
}

public ProxyService(MethodInterceptor methodInterceptor) {
this.methodInterceptor = methodInterceptor;
}

/**
* 原始功能方法
*
* @param message
* @return
*/
public String superSend(String message) {
return super.send(message);
}

/**
* 增强功能方法
*
* @param message
* @return
*/
@Override
public String send(String message) {
try {
return (String) methodInterceptor.intercept(
this,
method,
new Object[]{message},
methodProxy
);
} catch (Throwable e) {
throw new RuntimeException(e);
}
}
}

在调用目标方法时,不是通过 反射调用,而是通过 方法代理对象 调用方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
   @Test
public void test$Proxy() {

SmsService smsService = new SmsService();

ProxyService proxyService = new ProxyService(
(obj, method, args, proxy) -> {

log.info("before mothed:" + method.getName());
// 通过反射调用
// Object result = method.invoke(smsService, args);
// 避免通过 反射 调用
Object result = proxy.invokeSuper(obj, args);
log.info("after mothed:" + method.getName());
return result;
}
);

proxyService.send("Hello World!");
}
MethodProxy原理

MethodProxy 在调用 invokeinvokeSuper 会避免反射调用,它通过 FastClass 来避免反射,Cglib 在调用这两个方法时,会分别生成两个代理类(两个FastClass的子类),通过调用代理类中的方法避免反射

image-20230717002454447

methodProxy.invoke(代理目标对象,args)

当我们调用 Method.create() 静态方法时,底层会创建一个FastClass的子类(目的是避免方法的反射调用)

  • 当创建MethodProxy对象时,会构建Signature方法签名信息(包括方法名称和参数返回值)

image-20230717005336098

  • 代理类会根据传人的Signature定义目标方法的编号
  • 代理类中根据获取方法的定义的编号调用指定的方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public abstract class AbstractFastClass {

/**
* 获取目标的方法的序号
*
* @param signature 方法签名
* @return index 序号
*/
public abstract int getIndex(Signature signature);

/**
* 根据方法编号调用目标对象的方法
*
* @param index
* @param target
* @param args
* @return
*/
public abstract Object invoke(int index, Object target, Object[] args);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public class TargetFastClass extends AbstractFastClass {

/**
* 构建方法签名
*/
static Signature s0 = new Signature("save", "(Ljava/lang/String;)Ljava/lang/String;");

@Override
public int getIndex(Signature signature) {
if (s0.equals(signature)) {
return 0;
}
return -1;
}

@Override
public Object invoke(int index, Object target, Object[] args) {
if (index == 0) {
return (String) ((SmsService) target).send((String) args[0]);
}
return null;
}
}
1
2
3
4
5
6
7
8
@Test
public void testTargetFastClass() {
TargetFastClass targetFastClass = new TargetFastClass();
int index = targetFastClass.getIndex(
new Signature("send", "(Ljava/lang/String;)Ljava/lang/String;")
);
targetFastClass.invoke(index, new SmsService(), new Object[]{"Hello World!"});
}

image-20230717015128779

methodProxy.invokeSuper(代理对象,args)

调用 methodProxy.invokeSuper 的原理和调用 methodProxy.invoke 基本一致,唯一不同的是 获取的是 代理类中 的带原始方法的方法签名和定义编号,而 methodProxy.invoke 获取的是 代理目标类中的原始方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public class ProxyFastClass extends AbstractFastClass {

static Signature s0 = new Signature("superSend", "(Ljava/lang/String;)Ljava/lang/String;");

@Override
public int getIndex(Signature signature) {
if (s0.equals(signature)) {
return 0;
}
return -1;
}

@Override
public Object invoke(int index, Object target, Object[] args) {
if (index == 0) {
return (String) ((ProxyService) target).superSend((String) args[0]);
}
return null;
}
}

image-20230717020119732

1
2
3
4
5
6
7
8
9
@Test
public void testProxyFastClass() {
ProxyFastClass proxyFastClass = new ProxyFastClass();
int index = proxyFastClass.getIndex(
new Signature("superSend", "(Ljava/lang/String;)Ljava/lang/String;")
);
// new ProxyService(new DebugMethodInterceptor()) 为代理对象
proxyFastClass.invoke(index, new ProxyService(new DebugMethodInterceptor()), new Object[]{"Hello World!"});
}

Spring代理选择

Spring代理选择规则

切点:增强匹配的规则

通知:具体增强的逻辑

切面:切点和通知的组合

两个切面:aspectasvisor

aspect 是 通知和切点的组合集合

advisor 是 更细粒度的切面,只包含一个切点和通知

aspect 在生效之前会拆解成多个 advisor

切面实现

切点 在 org.springframework.aop 包下的 PointCut 接口实现

image-20230717151143591

可以使用 AspectJExpressionPointcut 根据 JExpression 表达式来进行模式匹配

image-20230717152358433

1
2
3
4
// 设置切点
AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();
// 设置切点表达式 execution([访问控制权限修饰符] 返回值类型 [全限定类名]方法名(形式参数列表) [异常])
pointcut.setExpression("execution(* submit())");

使用 MethodInterceptor 设置通知即功能增强

image-20230717162045054

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
@Test
public void testAop() {
// 设置切点
AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();
// execution([访问控制权限修饰符] 返回值类型 [全限定类名]方法名(形式参数列表) [异常])
pointcut.setExpression("execution(* submit())");
// 设置通知
MethodInterceptor methodInterceptor = new MethodInterceptor() {
@Override
public Object invoke(MethodInvocation invocation) throws Throwable {
logger.info("before submit");
// 调用目标
Object result = invocation.proceed();
logger.info("after submit");
return result;
}
};
// 组合切面(切点 + 通知)
DefaultPointcutAdvisor advisor = new DefaultPointcutAdvisor(pointcut, methodInterceptor);

// ProxyFactory 创建代理
ProxyFactory proxyFactory = new ProxyFactory();
// 设置代理对象
proxyFactory.setTarget(new TargetService1());
// 设置切面
proxyFactory.addAdvisor(advisor);

TargetService1 targetService1 = (TargetService1) proxyFactory.getProxy();
targetService1.execute();
targetService1.submit();
}

image-20230717161712244

通过 调试 发现,上述 实例 Spring 使用 Cglib 生成的代理对象

image-20230717161908379

代理选择

ProxyFactory间接继承ProxyConfigProxyConfig 内部存在一个成员变量 proxyTargetClass(默认为 false) 决定了 Spring 的代理方式

  • proxyTargetClass = false 时,代理目标实现接口,使用**JdkDynamicAopProxy**即 JDK 实现代理;代理没有实现接口,使用 **ObjenesisCglibAopProxy**即 Cglib 实现代理
  • proxyTargetClass = false 时,总使用**ObjenesisCglibAopProxy**即 Cglib 实现代理

image-20230718192414308

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
@Test
public void testAop() {
// 设置切点
AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();
// execution([访问控制权限修饰符] 返回值类型 [全限定类名]方法名(形式参数列表) [异常])
pointcut.setExpression("execution(* submit())");
// 设置通知
MethodInterceptor methodInterceptor = new MethodInterceptor() {
@Override
public Object invoke(MethodInvocation invocation) throws Throwable {
logger.info("before submit");
// 调用目标
Object result = invocation.proceed();
logger.info("after submit");
return result;
}
};
// 组合切面(切点 + 通知)
DefaultPointcutAdvisor advisor = new DefaultPointcutAdvisor(pointcut, methodInterceptor);

// 代理目标对象
TargetService1 targetService = new TargetService1();

// ProxyFactory 创建代理
ProxyFactory proxyFactory = new ProxyFactory();
// 设置代理对象
proxyFactory.setTarget(targetService);
// 设置代理对象实现的接口 (如果不设置,默认认为 代理目标对象 没有实现接口)
proxyFactory.setInterfaces(targetService.getClass().getInterfaces());

// 设置切面
proxyFactory.addAdvisor(advisor);


Target targetService1 = (Target) proxyFactory.getProxy();
targetService1.execute();
targetService1.submit();
}

image-20230719000226624

image-20230719000404857

切点匹配

常见切点匹配实现

Spring切点PointCut 判断将来的目标方法 是否要进行功能增强。AspectJExpressionPointcutPointCut 的一种具体实现,它根据切点表达式进行方法的模式匹配。

创建 AspectJExpressionPointcut 对象,调用 setExpression 设置切点表达式,可以通过 matches 方法判断是否与切点表达式匹配

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@Transactional(rollbackFor = Exception.class)
public class TransactionalService {

private static final Logger logger = LoggerFactory.getLogger(TransactionalService.class);

@Transactional(rollbackFor = Exception.class)
public void execute() {
logger.info("execute");
}

public void submit() {
logger.info("submit");
}
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@Test
public void testTarget() throws NoSuchMethodException {

AspectJExpressionPointcut aspectJExpressionPointcut1 = new AspectJExpressionPointcut();
// 设置 切点表达式:判断方法是否与切点表达式匹配
aspectJExpressionPointcut1.setExpression("execution(* submit())");
// 判断 类中的方法是否匹配 AspectJExpressionPointcut.matches(Method method, Class<?> targetClass)
logger.info("execute:{}", aspectJExpressionPointcut1.matches(TargetService.class.getMethod("execute"), TargetService.class));
logger.info("submit:{}", aspectJExpressionPointcut1.matches(TargetService.class.getMethod("submit"), TargetService.class));

AspectJExpressionPointcut aspectJExpressionPointcut2 = new AspectJExpressionPointcut();
// 设置 切点表达式:判断方法上的注解类型是否与切点表达式匹配
aspectJExpressionPointcut2.setExpression("@annotation(org.springframework.transaction.annotation.Transactional)");
logger.info("execute:{}", aspectJExpressionPointcut2.matches(TargetService.class.getMethod("execute"), TargetService.class));
logger.info("submit:{}", aspectJExpressionPointcut2.matches(TargetService.class.getMethod("submit"), TargetService.class));
}

image-20230719010400001

@Transaction实现

AspectJExpressionPointcut 只能对于方法进行模式匹配,不能匹配类上的和接口上

StaticMethodMatcherPointcut 是一个实现 PointCut 的抽象类,可以规定 具体的匹配规则

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
@Test
public void testTransactionalAnnotation() throws NoSuchMethodException {

// StaticMethodMatcherPointcut 是一个实现 PointCut 的抽象类,可以规定 具体的匹配规则
StaticMethodMatcherPointcut staticMethodMatcherPointcut = new StaticMethodMatcherPointcut() {
@Override
public boolean matches(Method method, Class<?> targetClass) {

// 通过 MergedAnnotations 工具类获取 方法 上的注解
// MergedAnnotations.SearchStrategy.TYPE_HIERARCHY : 对整个类型层次结构(包括超类和实现的接口)执行完整搜索 即 实现的接口 上的注解也可以获取到
MergedAnnotations mergedAnnotations = MergedAnnotations.from(method, MergedAnnotations.SearchStrategy.TYPE_HIERARCHY);
// 判断 方法上是否添加了 Transactional 注解
if (mergedAnnotations.isPresent(Transactional.class)) {
return true;
}

// 通过 MergedAnnotations 工具类获取 类 上的注解
mergedAnnotations = MergedAnnotations.from(targetClass, MergedAnnotations.SearchStrategy.TYPE_HIERARCHY);
// 判断 类上是否添加了 Transactional 注解
if (mergedAnnotations.isPresent(Transactional.class)) {
return true;
}
return false;
}
};
logger.info("execute:{}", staticMethodMatcherPointcut.matches(TransactionalService.class.getMethod("execute"), TransactionalService.class));
logger.info("submit:{}", staticMethodMatcherPointcut.matches(TransactionalService.class.getMethod("submit"), TransactionalService.class));
}

image-20230719014817487

从@Aspect到Advisor

Spring 切面分为 @Aspect切面 和 Advisor 切面

@Aspect 可以有多个切点和切面,Advisor 只能有一个切点和切面

Spring 处理 高级的 @Aspect 切面,会将 高级的 @Aspect 切面 转换 低级 Advisor 切面

高级 @Aspect 切面

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@Aspect
public class TestAspect {

private static final Logger logger = LoggerFactory.getLogger(TestAspect.class);

@Before("execution(* submit())")
public void before() {
logger.info("aspect before");
}

@After("execution(* submit())")
public void after() {
logger.info("aspect after");
}
}

低级 Advisor 切面

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
@Configuration
public class AdvisorConfig {

private static final Logger logger = LoggerFactory.getLogger(AdvisorConfig.class);

@Bean
public Advisor testAdvisor(MethodInterceptor testMethodInterceptor) {

AspectJExpressionPointcut aspectJExpressionPointcut = new AspectJExpressionPointcut();
aspectJExpressionPointcut.setExpression("execution(* submit())");

return new DefaultPointcutAdvisor(aspectJExpressionPointcut, testMethodInterceptor);
}

@Bean
public MethodInterceptor testMethodInterceptor() {
return invocation -> {
logger.info("advisor before");
Object result = invocation.proceed();
logger.info("advisor after");
return result;
};
}
}

AnnotationAwareAspectJAutoProxyCreator 后置处理器

  • 找到所有的切面,将所有的 高级 Aspect 切面转换为 Advisor 切面

  • 调用 ProxyFactory 创建代理对象

AnnotationAwareAspectJAutoProxyCreator 后置处理器的核心方法
  • 查找所有符合条件的 切面 并 将高级的 Aspect 切面转换为 Advisor 切面

image-20230719212839646

  • 为 有必要的 Bean 即有资格(模式匹配上的)来创建代理对象,内部调用了 findEligibleAdvisors ,当 Advisor 集合不为空则 创建代理对象

image-20230719212940517

由于 AnnotationAwareAspectJAutoProxyCreator 后处理器,方法由 protect 修饰,所以 只能同一个包下/子类/反射 可以调用。这里 测试类包名修改成与 AnnotationAwareAspectJAutoProxyCreator 位置一致。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
package org.springframework.aop.framework.autoproxy;

import com.example.demo.advisor.AdvisorConfig;
import com.example.demo.aspect.TestAspect;
import lombok.extern.slf4j.Slf4j;
import org.junit.Test;
import org.springframework.aop.Advisor;
import org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.annotation.ConfigurationClassPostProcessor;
import org.springframework.context.support.GenericApplicationContext;

import java.util.List;

@Slf4j
@SpringBootTest
public class SpringDemoAopTest {

static class Target {
public void execute() {
log.info("execute");
}

public void submit() {
log.info("submit");
}
}

@Test
public void testPointCut() {
GenericApplicationContext genericApplicationContext = new GenericApplicationContext();
// 添加 Bean
genericApplicationContext.registerBean("testAspect", TestAspect.class);
genericApplicationContext.registerBean("advisorConfig", AdvisorConfig.class);

// 后置处理器
genericApplicationContext.registerBean(ConfigurationClassPostProcessor.class);
genericApplicationContext.registerBean(AnnotationAwareAspectJAutoProxyCreator.class);

genericApplicationContext.refresh();

AnnotationAwareAspectJAutoProxyCreator creator = genericApplicationContext.getBean(AnnotationAwareAspectJAutoProxyCreator.class);

// 将 TargetService1 与 容器中 PointCut 进行匹配,如果匹配则添加到 Advisor 集合中
List<Advisor> advisor1 = creator.findEligibleAdvisors(Target.class, "target");
advisor1.forEach(advisor -> log.info("advisor:{}", advisor));

// 判断是否有资格被代理并返回代理对象
Object o = creator.wrapIfNecessary(new Target(), "target", "target");
log.info("class:{}", o.getClass());
Target target = (Target) o;
target.submit();
}
}

image-20230719214930468

image-20230720022254338

高级转换低级时机和代理生成时机

代理对象的创建时机一般是在 初始化之后 ,另外 当发生循环依赖时, 会发生在 创建实例 和 依赖注入之间,因为在 依赖注入的对象 并非 原始对象,而是代理对象

1
创建实例 -> (*) 依赖注入 -> 初始化(*)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
@Slf4j
@SpringBootTest
public class SpringDemoProxyTest {

@Configuration
static class Config {

/**
* 解析切面并生成代理
*
* @return
*/
@Bean
public AnnotationAwareAspectJAutoProxyCreator annotationAwareAspectJAutoProxyCreator() {
return new AnnotationAwareAspectJAutoProxyCreator();
}

/**
* 解析 Autowired
*
* @return
*/
@Bean
public AutowiredAnnotationBeanPostProcessor autowiredAnnotationBeanPostProcessor() {
return new AutowiredAnnotationBeanPostProcessor();
}

/**
* 解析 @PostConstruct
*
* @return
*/
@Bean
public CommonAnnotationBeanPostProcessor commonAnnotationBeanPostProcessor() {
return new CommonAnnotationBeanPostProcessor();
}

/**
* 切面
*
* @param methodInterceptor
* @return
*/
@Bean
public Advisor advisor(MethodInterceptor methodInterceptor) {
AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();
pointcut.setExpression("execution(* submit())");

return new DefaultPointcutAdvisor(pointcut, methodInterceptor);
}

/**
* 通知
*
* @return
*/
@Bean
public MethodInterceptor methodInterceptor() {
return invocation -> {
log.info("before");
Object result = invocation.proceed();
log.info("after");
return result;
};
}

@Bean
public Bean1 bean1() {
return new Bean1();
}

@Bean
public Bean2 bean2() {
return new Bean2();
}
}

static class Bean1 {

public Bean1() {
log.info("构造方法");
}

public void submit() {
log.info("submit");
}

@PostConstruct
public void init() {
log.info("init");
}

@Autowired
public void setBean2(Bean2 bean2) {
log.info("依赖注入:{}", bean2.getClass());
}
}

static class Bean2 {

public Bean2() {
log.info("构造方法");
}

@Autowired
public void setBean1(Bean1 bean1) {
log.info("依赖注入:{}", bean1.getClass());
}

public void submit() {
log.info("submit");
}

@PostConstruct
public void init() {
log.info("init");
}
}

@Test
public void test() {
GenericApplicationContext genericApplicationContext = new GenericApplicationContext();
genericApplicationContext.registerBean(ConfigurationClassPostProcessor.class);
genericApplicationContext.registerBean(Config.class);
genericApplicationContext.refresh();
genericApplicationContext.close();
}
}

我们分析一下 依赖注入的情况:当注入Bean1时,首先调用 Bean1 的构造,然后进行依赖注入 Bean2 ,此时 Bean2 并没有,此时去 Bean2 的生成流程,先构造,再进行依赖注入,在依赖注入时,需要一个 被代理的 Bean1,此时发生 Bean1 的代理在 Bean1 依赖注入之前被创建,创建代理的对象被创建并存放到二级缓存中

但是 依赖注入与初始化 不应该被增强,仍然使用的是原始对象

image-20230720170350065

Order 切面优先级

切面执行的优先级 可以被控制

  • 高级切面上,可以添加 @Order 注解

  • 低级切面上,可以通过 DefaultPointcutAdvisor.setOrder() 方法设置 优先级

    Order 的值越小 切面的优先级越高

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
@Configuration
public class AdvisorConfig {

private static final Logger logger = LoggerFactory.getLogger(AdvisorConfig.class);

@Bean
public Advisor testAdvisor(MethodInterceptor testMethodInterceptor) {

AspectJExpressionPointcut aspectJExpressionPointcut = new AspectJExpressionPointcut();
aspectJExpressionPointcut.setExpression("execution(* submit())");

DefaultPointcutAdvisor advisor = new DefaultPointcutAdvisor(aspectJExpressionPointcut, testMethodInterceptor);
advisor.setOrder(2);
return advisor;
}

@Bean
public MethodInterceptor testMethodInterceptor() {
return invocation -> {
logger.info("advisor before");
Object result = invocation.proceed();
logger.info("advisor after");
return result;
};
}
}

image-20230720175241497

高级切面转换为低级切面

调用 AnnotationAwareAspectJAutoProxyCreator.wrapIfNecessary() 判断是否有资格被代理并返回代理对象,该方法内部会调用 findEligibleAdvisors() 方法进行匹配 符合条件的PointCut 添加到 Advisor 集合中,并将 高级切面 转换为 低级切面

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
@Test
public void testFindEligibleAdvisors() {
// 将 Aspect 高级切面 转换为 低级 Advisor 切面

// 切面实例工厂
AspectInstanceFactory aspectInstanceFactory = new SingletonAspectInstanceFactory(new TestAspect());

// 转换后的 advisors 集合
List<Advisor> advisors = new ArrayList<>();

// 获取 类上所有的方法
for (Method declaredMethod : TestAspect.class.getDeclaredMethods()) {
// 判断方法上是否有注解
if (declaredMethod.isAnnotationPresent(Before.class)) {
Before annotation = declaredMethod.getAnnotation(Before.class);

AspectJExpressionPointcut aspectJExpressionPointcut = new AspectJExpressionPointcut();
aspectJExpressionPointcut.setExpression(annotation.value());

// 创建 前置通知 底层通知类
AspectJMethodBeforeAdvice aspectJMethodBeforeAdvice = new AspectJMethodBeforeAdvice(
declaredMethod,
aspectJExpressionPointcut,
aspectInstanceFactory
);

DefaultPointcutAdvisor defaultPointcutAdvisor = new DefaultPointcutAdvisor(aspectJExpressionPointcut, aspectJMethodBeforeAdvice);

advisors.add(defaultPointcutAdvisor);
}
}

advisors.forEach(advisor -> log.info("advisor:{}", advisor));
}

image-20230720214359985

输出 一个 Advisor 切面

image-20230720214343041

底层通知实现类
  • 前置通知底层通知实现类:AspectJMethodBeforeAdvice
  • 环绕通知底层通知实现类:AspectJAroundAdvice
  • 返回通知底层通知实现类:AspectJAfterReturningAdvice
  • 异常通知底层通知实现类:AspectJAfterThrowingAdvice
  • 后置通知底层通知实现类:AspectJAfterAdvice

静态通知调用

适配器模式

不同通知都会统一转换为环绕通知 MethodInterceptor

无论 ProxyFactory 基于什么方式创建代理对象,都会被统一转换为一个 MethodInterceptor 对象执行,这体现了适配器模式。做到 对于外部区分 BeforeAroundAfterReturning,(AfterAfterThrowing 本身已经实现了 MethodInterceptor 无需转换) ,内部统一使用 环绕通知,同意转换为 MethodInterceptor 对象执行

由于 Advisor 可能存在多个,一个接着一个的调用,因此需要一个调用链对象 MethodInterceptor

img

image-20230721175837511

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
@Test
public void testFindEligibleAdvisors() throws NoSuchMethodException {
// 将 Aspect 高级切面 转换为 低级 Advisor 切面

// 切面实例工厂
AspectInstanceFactory aspectInstanceFactory = new SingletonAspectInstanceFactory(new TestAspect());

// 转换后的 advisors 集合
List<Advisor> advisors = new ArrayList<>();

// 获取 类上所有的方法
for (Method declaredMethod : TestAspect.class.getDeclaredMethods()) {
// 判断方法上是否有注解
if (declaredMethod.isAnnotationPresent(Before.class)) {
Before annotation = declaredMethod.getAnnotation(Before.class);

AspectJExpressionPointcut aspectJExpressionPointcut = new AspectJExpressionPointcut();
aspectJExpressionPointcut.setExpression(annotation.value());

// 创建 前置通知底层通知类
AspectJMethodBeforeAdvice aspectJMethodBeforeAdvice = new AspectJMethodBeforeAdvice(
declaredMethod,
aspectJExpressionPointcut,
aspectInstanceFactory
);

DefaultPointcutAdvisor defaultPointcutAdvisor = new DefaultPointcutAdvisor(aspectJExpressionPointcut, aspectJMethodBeforeAdvice);

advisors.add(defaultPointcutAdvisor);
} else if (declaredMethod.isAnnotationPresent(AfterReturning.class)) {
AfterReturning annotation = declaredMethod.getAnnotation(AfterReturning.class);

AspectJExpressionPointcut aspectJExpressionPointcut = new AspectJExpressionPointcut();
aspectJExpressionPointcut.setExpression(annotation.value());

// 创建 前置通知底层通知类
AspectJAfterReturningAdvice aspectJAfterReturningAdvice = new AspectJAfterReturningAdvice(
declaredMethod,
aspectJExpressionPointcut,
aspectInstanceFactory
);

DefaultPointcutAdvisor defaultPointcutAdvisor = new DefaultPointcutAdvisor(aspectJExpressionPointcut, aspectJAfterReturningAdvice);

advisors.add(defaultPointcutAdvisor);
} else if (declaredMethod.isAnnotationPresent(Around.class)) {
Around annotation = declaredMethod.getAnnotation(Around.class);

AspectJExpressionPointcut aspectJExpressionPointcut = new AspectJExpressionPointcut();
aspectJExpressionPointcut.setExpression(annotation.value());

// 创建 前置通知底层通知类
AspectJAroundAdvice aspectJAroundAdvice = new AspectJAroundAdvice(
declaredMethod,
aspectJExpressionPointcut,
aspectInstanceFactory
);

DefaultPointcutAdvisor defaultPointcutAdvisor = new DefaultPointcutAdvisor(aspectJExpressionPointcut, aspectJAroundAdvice);

advisors.add(defaultPointcutAdvisor);
}
}

advisors.forEach(advisor -> log.info("advisor:{}", advisor));

// 通过 代理工厂 创建 代理对象
ProxyFactory proxyFactory = new ProxyFactory();
proxyFactory.setTarget(new Target());
proxyFactory.addAdvisors(advisors);

// 获取 代理对象即执行对象 通知的集合
List<Object> interceptorsAndDynamicInterceptionAdvices = proxyFactory.getInterceptorsAndDynamicInterceptionAdvice(Target.class.getMethod("submit"), Target.class);
interceptorsAndDynamicInterceptionAdvices.forEach(interceptorsAndDynamicInterceptionAdvice ->
log.info("interceptorsAndDynamicInterceptionAdvice:{}", interceptorsAndDynamicInterceptionAdvice));
}

image-20230721175935396

适配器

MethodBeforeAdviceAdapterAspectJMethodBeforeAdvice 转换为 MethodInterceptor

在创建代理对象时,通过适配器将 通知 统一转换为 环绕通知MethodInterceptor

image-20230721181536799

image-20230721181052056

责任链模式

代理对象 内部通过 调用链接口 MethodInvocation 调用 目标对象 和 环绕通知集合

1
2
3
protected ReflectiveMethodInvocation(
Object proxy, @Nullable Object target, Method method, @Nullable Object[] arguments,
@Nullable Class<?> targetClass, List<Object> interceptorsAndDynamicMethodMatchers)

image-20230721220341020

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
@Slf4j
@SpringBootTest
public class SpringDemoAdvisorTest {

static class Target {

public void execute() {
log.info("execute");
}

public void submit() {
log.info("submit");
}
}

@Test
public void testFindEligibleAdvisors() throws Throwable {
// 将 Aspect 高级切面 转换为 低级 Advisor 切面

// 切面实例工厂
AspectInstanceFactory aspectInstanceFactory = new SingletonAspectInstanceFactory(new TestAspect());

// 转换后的 advisors 集合
List<Advisor> advisors = new ArrayList<>();

// 获取 类上所有的方法
for (Method declaredMethod : TestAspect.class.getDeclaredMethods()) {
// 判断方法上是否有注解
if (declaredMethod.isAnnotationPresent(Before.class)) {
Before annotation = declaredMethod.getAnnotation(Before.class);

AspectJExpressionPointcut aspectJExpressionPointcut = new AspectJExpressionPointcut();
aspectJExpressionPointcut.setExpression(annotation.value());

// 创建 前置通知底层通知类
AspectJMethodBeforeAdvice aspectJMethodBeforeAdvice = new AspectJMethodBeforeAdvice(
declaredMethod,
aspectJExpressionPointcut,
aspectInstanceFactory
);

DefaultPointcutAdvisor defaultPointcutAdvisor = new DefaultPointcutAdvisor(aspectJExpressionPointcut, aspectJMethodBeforeAdvice);

advisors.add(defaultPointcutAdvisor);
} else if (declaredMethod.isAnnotationPresent(AfterReturning.class)) {
AfterReturning annotation = declaredMethod.getAnnotation(AfterReturning.class);

AspectJExpressionPointcut aspectJExpressionPointcut = new AspectJExpressionPointcut();
aspectJExpressionPointcut.setExpression(annotation.value());

// 创建 前置通知底层通知类
AspectJAfterReturningAdvice aspectJAfterReturningAdvice = new AspectJAfterReturningAdvice(
declaredMethod,
aspectJExpressionPointcut,
aspectInstanceFactory
);

DefaultPointcutAdvisor defaultPointcutAdvisor = new DefaultPointcutAdvisor(aspectJExpressionPointcut, aspectJAfterReturningAdvice);

advisors.add(defaultPointcutAdvisor);
} else if (declaredMethod.isAnnotationPresent(Around.class)) {
Around annotation = declaredMethod.getAnnotation(Around.class);

AspectJExpressionPointcut aspectJExpressionPointcut = new AspectJExpressionPointcut();
aspectJExpressionPointcut.setExpression(annotation.value());

// 创建 前置通知底层通知类
AspectJAroundAdvice aspectJAroundAdvice = new AspectJAroundAdvice(
declaredMethod,
aspectJExpressionPointcut,
aspectInstanceFactory
);

DefaultPointcutAdvisor defaultPointcutAdvisor = new DefaultPointcutAdvisor(aspectJExpressionPointcut, aspectJAroundAdvice);

advisors.add(defaultPointcutAdvisor);
}
}

advisors.forEach(advisor -> log.info("advisor:{}", advisor));

// 通过 代理工厂 创建 代理对象
Target target = new Target();
ProxyFactory proxyFactory = new ProxyFactory();
proxyFactory.setTarget(target);
// 将 MethodInvocation 放入当前线程
proxyFactory.addAdvice(ExposeInvocationInterceptor.INSTANCE);
proxyFactory.addAdvisors(advisors);

// 获取 代理对象即执行对象 通知的集合
List<Object> interceptorsAndDynamicInterceptionAdvices =
proxyFactory.getInterceptorsAndDynamicInterceptionAdvice(
Target.class.getMethod("submit"),
Target.class
);
interceptorsAndDynamicInterceptionAdvices.forEach(interceptorsAndDynamicInterceptionAdvice ->
log.info("interceptorsAndDynamicInterceptionAdvice:{}", interceptorsAndDynamicInterceptionAdvice));

// 创建调用链对象
MethodInvocation methodInvocation =
new ReflectiveMethodInvocation(
null,
target,
Target.class.getMethod("submit"),
new Object[0],
Target.class,
interceptorsAndDynamicInterceptionAdvices
);
methodInvocation.proceed();
}
}

在调用链执行 Advisor通知 时,某些通知内部可能用到 MethodInvocation 调用链对象,注意要添加 proxyFactory.addAdvice(ExposeInvocationInterceptor.INSTANCE) ,将 MethodInvocation 放入当前线程(即外部一个公共的位置),让所有的通知可以获取到 MethodInvocation 调用链对象

image-20230722034351217

调用链实现

间接递归 实现 调用每一个环绕通知以及目标方法 - 责任链模式

image-20230726162514322

动态通知调用

动态通知:有参数绑定的通知,执行时需要获取切点对象来进行参数匹配和绑定吗

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
@Slf4j
@SpringBootTest
public class SpringAopDynamicTest {

@Aspect
static class MyAspect {

/**
* 动态通知调用
*
* @param x
*/
@Before("execution(* submit(..)) && args(x)")
public void before(int x) {
log.info("before:{}", x);
}
}

static class Target {

public void submit(int x) {
log.info("submit:{}", x);
}
}

@Configuration
static class MyConfig {

@Bean
public AnnotationAwareAspectJAutoProxyCreator annotationAwareAspectJAutoProxyCreator() {
return new AnnotationAwareAspectJAutoProxyCreator();
}

@Bean
public MyAspect myAspect() {
return new MyAspect();
}
}

@Test
public void test() throws Throwable {
GenericApplicationContext genericApplicationContext = new GenericApplicationContext();
genericApplicationContext.registerBean(ConfigurationClassPostProcessor.class);
genericApplicationContext.registerBean(MyConfig.class);
genericApplicationContext.refresh();

AnnotationAwareAspectJAutoProxyCreator creator =
genericApplicationContext.getBean(AnnotationAwareAspectJAutoProxyCreator.class);
List<Advisor> advisors = creator.findEligibleAdvisors(Target.class, "target");

Target target = new Target();
ProxyFactory proxyFactory = new ProxyFactory();
proxyFactory.setTarget(target);
proxyFactory.addAdvisors(advisors);
Object proxy = proxyFactory.getProxy();

List<Object> interceptorsAndDynamicInterceptionAdvices =
proxyFactory.getInterceptorsAndDynamicInterceptionAdvice(Target.class.getMethod("submit", int.class), Target.class);
interceptorsAndDynamicInterceptionAdvices.forEach(o -> log.info("interceptorsAndDynamicInterceptionAdvice:{}", o));

interceptorsAndDynamicInterceptionAdvices.forEach(o -> {
try {
Class<?> aClass = Class.forName("org.springframework.aop.framework.InterceptorAndDynamicMethodMatcher");
if (aClass.isInstance(o)) {
Field interceptor = aClass.getDeclaredField("interceptor");
interceptor.setAccessible(true);
Field methodMatcher = aClass.getDeclaredField("methodMatcher");
methodMatcher.setAccessible(true);
log.info("InterceptorAndDynamicMethodMatcher对象:{}", o);
log.info("interceptor对象:{}", interceptor.get(o));
log.info("methodMatcher对象:{}", methodMatcher.get(o));
}

} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
} catch (NoSuchFieldException e) {
throw new RuntimeException(e);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
}
});
// new ReflectiveMethodInvocation() 属于私有方法 通过 创建子类 调用
MethodInvocation methodInvocation =
new ReflectiveMethodInvocation(
proxy,
target,
Target.class.getMethod("submit", int.class),
new Object[]{100},
Target.class,
interceptorsAndDynamicInterceptionAdvices
) {
};

methodInvocation.proceed();
}
}

image-20230727020301364

InterceptorAndDynamicMethodMatcher 属性中包含 环绕通知 和 匹配切点(为了支持动态方法调用)

image-20230727020429481

image-20230727022427047