1. Spring创建代理原理
1.1 ProxyFactory类
第一步:创建一个基础SpringBoot项目
<!--web-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- aop-starter -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
第二步:创建一个测试类
package com.lvpt.circular;
/**
* 创建代理原理
* @author jgy
* @date 2022-09-14
**/
public class App01 {
public static void main(String[] args) {
//aspect(切面) = advice(通知) + pointcut(切点),切面类就是可用抽离出来的公共代码
//advisor = 更细粒度的切面,包含一个通知和切点
}
interface I1{
void foo();
void bar();
}
static class Target1 implements I1{
@Override
public void foo(){
System.out.println("target1 foo");
}
@Override
public void bar() {
System.out.println("target1 bar");
}
}
}
第三步:写一个测试方法,使用ProxyFactory实现增强
/**
* 代理工厂 proxyFactory测试1
**/
public void proxyFactoryTest1(){
//1、创建代理工厂
ProxyFactory proxyFactory = new ProxyFactory();
//2、指定代理对象
proxyFactory.setTarget(new Target1());
//3、添加通知: MethodInterceptor: 方法拦截器,属于环绕通知; 底层还是调的addAdvisor(),
//用了Pointcut.TRUE: 即匹配所有方法: DefaultPointcutAdvisor(Pointcut.TRUE, new MethodInterceptor)
proxyFactory.addAdvice((MethodInterceptor) invocation -> {
try {
System.out.println("前置增强....");
//调用目标
return invocation.proceed();
}finally {
System.out.println("后置增强....");
}
});
//我们也可用改变代理方式,设置代理方式为JDK代理: 默认CGLib
proxyFactory.addInterface(I1.class);
//这是就需要写成接口类型
I1 proxy = (I1)proxyFactory.getProxy();
//强制指定用CGLib: true:CGLib; false:JDK
//proxyFactory.setProxyTargetClass(true);
//4、拿到代理对象: CGLib代理方式(默认)
//Target1 proxy =(Target1) proxyFactory.getProxy();
//5、调用增强后的方法
proxy.foo();
proxy.bar();
//打印类名,可用知道用的是CGLib代理
System.out.println("代理方式: " + proxy.getClass().getName());
}
测试结果:都得到增强
前置增强....
target1 foo
后置增强....
前置增强....
target1 bar
后置增强....
com.lvpt.circular.$Proxy0
第四步:再写一个测试方法,添加AspectJExpressionPointcut:切点表达式,只增强指定方法
/**
* 代理工厂: proxyFactory测试2
**/
public void proxyFactoryTest2(){
//1、创建代理工厂
ProxyFactory proxyFactory = new ProxyFactory();
//2、指定代理对象
proxyFactory.setTarget(new Target1());
//3、获取AspectJ切点表达式
AspectJExpressionPointcut expressionPointcut = new AspectJExpressionPointcut();
//4、定义切点表达式
expressionPointcut.setExpression("execution(* foo())");
//5、创建通知: 使用默认通知DefaultPointcutAdvisor,
//参数为: 切点表达式 + 通知(这就是advisor,只有一个切面,也就是这两个参数)
proxyFactory.addAdvisor(new DefaultPointcutAdvisor(expressionPointcut, (MethodInterceptor) invocation -> {
try {
System.out.println("前置增强....");
//调用目标
return invocation.proceed();
}finally {
System.out.println("后置增强....");
}
}));
//再次添加切面Advisor(可用多个)
proxyFactory.addAdvisor(new DefaultPointcutAdvisor(expressionPointcut, (MethodInterceptor) invocation -> {
try {
System.out.println("前置增强22....");
//调用目标
return invocation.procee