## AopProxy
- [AopProxy](#aopproxy)
- [一、基本信息](#一基本信息)
- [二、基本描述](#二基本描述)
- [三、主要功能](#三主要功能)
- [四、接口源码](#四接口源码)
- [五、主要实现](#五主要实现)
- [六、最佳实践](#六最佳实践)
- [JDK动态代理](#jdk动态代理)
- [CGLIB代理](#cglib代理)
- [七、时序图](#七时序图)
- [JdkDynamicAopProxy](#jdkdynamicaopproxy)
- [CglibAopProxy](#cglibaopproxy)
- [七、源码分析](#七源码分析)
- [JdkDynamicAopProxy](#jdkdynamicaopproxy-1)
- [CglibAopProxy](#cglibaopproxy-1)
- [八、常见问题](#八常见问题)
### 一、基本信息
✒️ **作者** - Lex 📝 **博客** - [掘金](https://juejin.cn/user/4251135018533068/posts) 📚 **源码地址** - [github](https://github.com/xuchengsheng/spring-reading)
### 二、基本描述
`AopProxy` 接口是Spring框架中用于支持面向切面编程(AOP)的关键组件之一,它定义了生成代理对象的标准接口,允许在运行时动态地创建代理对象,以实现对目标对象的方法调用进行拦截和增强。
### 三、主要功能
1. **代理对象的创建与管理**
+ `AopProxy` 接口定义了创建和管理代理对象的标准方法,可以通过这些方法在运行时动态地生成代理对象。
2. **对目标对象方法的拦截与增强**
+ AOP代理对象通过 `AopProxy` 接口实现对目标对象方法的拦截,允许在方法执行前、后或异常时执行额外的逻辑,从而实现对方法行为的增强。
3. **支持不同的代理方式**
+ `AopProxy` 接口支持多种代理方式,包括JDK动态代理和CGLIB代理。这样可以根据目标对象是否实现接口来选择合适的代理方式。
4. **实现AOP的横切关注点**
+ 通过 `AopProxy` 接口,可以将AOP的横切关注点与业务逻辑进行分离,提高了代码的模块化和可维护性,同时也使得横切关注点可以被重用在多个不同的业务逻辑中。
### 四、接口源码
`AopProxy` 接口是一个委托接口,用于配置AOP代理,并允许创建实际的代理对象。它提供了两个方法用于创建代理对象,第一个方法使用默认的类加载器创建代理对象,通常是线程上下文类加载器;第二个方法允许指定类加载器创建代理对象。可以使用JDK动态代理或者CGLIB代理技术来生成代理对象。
```java
/**
* 配置AOP代理的委托接口,允许创建实际的代理对象。
*
*
默认情况下,可用于创建代理对象的实现包括JDK动态代理和CGLIB代理,
* 这些代理实现由 {@link DefaultAopProxyFactory} 应用。
*
* @author Rod Johnson
* @author Juergen Hoeller
* @see DefaultAopProxyFactory
*/
public interface AopProxy {
/**
* 创建一个新的代理对象。
*
使用AopProxy的默认类加载器(必要时用于代理创建):
* 通常为线程上下文类加载器。
* @return 新的代理对象(永远不会是 {@code null})
* @see Thread#getContextClassLoader()
*/
Object getProxy();
/**
* 创建一个新的代理对象。
*
使用给定的类加载器(必要时用于代理创建)。
* 如果给定的类加载器为 {@code null},则简单地传递并因此导致低级代理工具的默认值,
* 这通常不同于AopProxy实现的 {@link #getProxy()} 方法选择的默认值。
* @param classLoader 用于创建代理的类加载器
* (或 {@code null} 表示使用低级代理工具的默认值)
* @return 新的代理对象(永远不会是 {@code null})
*/
Object getProxy(@Nullable ClassLoader classLoader);
}
```
### 五、主要实现
1. **JdkDynamicAopProxy**
+ 使用 JDK 动态代理实现的 `AopProxy` 实现类。当目标对象实现了至少一个接口时,Spring 将使用该类创建代理对象。该类通过 Java 标准库中的 `java.lang.reflect.Proxy` 类来创建代理对象。
2. **CglibAopProxy**
+ 使用 CGLIB(Code Generation Library)动态代理实现的 `AopProxy` 实现类。当目标对象没有实现任何接口时,Spring 将使用该类创建代理对象。该类通过生成目标类的子类来创建代理对象,实现了对目标对象方法的拦截和增强。
### 六、最佳实践
#### JDK动态代理
使用 JDK 动态代理来创建 AOP 代理对象。在 `jdkProxy` 方法中,通过配置 `AdvisedSupport` 对象,设置目标对象和接口,然后利用反射创建 `JdkDynamicAopProxy` 实例,并调用 `AopProxy` 接口的 `getProxy` 方法生成代理对象。最后,输出代理对象的信息和调用代理对象方法的结果。
```java
public class AopProxyDemo {
public static void main(String[] args) throws Exception {
jdkProxy();
}
/**
* Jdk代理
*
* @throws Exception
*/
private static void jdkProxy() throws Exception {
// 创建AdvisedSupport对象,用于配置AOP代理
AdvisedSupport advisedSupport = new AdvisedSupport();
// 设置目标对象
advisedSupport.setTarget(new MyServiceImpl());
// 设置目标对象实现的接口
advisedSupport.setInterfaces(MyService.class);
// 获取JdkDynamicAopProxy的Class对象
Class jdkClass = Class.forName("org.springframework.aop.framework.JdkDynamicAopProxy");
// 获取JdkDynamicAopProxy的构造方法
Constructor constructor = jdkClass.getConstructor(AdvisedSupport.class);
constructor.setAccessible(true);
// 使用构造方法创建JdkDynamicAopProxy实例
AopProxy aopProxy = (AopProxy) constructor.newInstance(advisedSupport);
// 调用getProxy方法创建代理对象
MyService myService = (MyService) aopProxy.getProxy();
// 输出代理对象的信息
System.out.println("JDK Class = " + myService.getClass());
// 调用代理对象的方法
System.out.println("doSomething method result = " + myService.doSomething());
}
}
```
运行结果,代理对象的类为 `com.sun.proxy.$Proxy0`,调用代理对象的 `doSomething` 方法结果为 `"hello world"`。
```java
JDK Class = class com.sun.proxy.$Proxy0
doSomething method result = hello world
```
#### CGLIB代理
使用 CGLIB 动态代理来创建 AOP 代理对象。在 `cglibProxy` 方法中,通过配置 `AdvisedSupport` 对象,设置目标对象,然后利用反射创建 `CglibAopProxy` 实例,并调用 `AopProxy` 接口的 `getProxy` 方法生成代理对象。最后,输出代理对象的信息和调用代理对象方法的结果。
```java
public class AopProxyDemo {
public static void main(String[] args) throws Exception {
cglibProxy();
}
/**
* cglib代理
*
* @throws Exception
*/
private static void cglibProxy() throws Exception {
// 创建AdvisedSupport对象,用于配置AOP代理
AdvisedSupport advisedSupport = new AdvisedSupport();
// 设置目标对象
advisedSupport.setTarget(new MyServiceImpl());
// 获取CglibAopProxy的Class对象
Class cglibClass = Class.forName("org.springframework.aop.framework.CglibAopProxy");
// 获取CglibAopProxy的构造方法
Constructor constructor = cglibClass.getConstructor(AdvisedSupport.class);
constructor.setAccessible(true);
// 使用构造方法创建CglibAopProxy实例
AopProxy aopProxy = (AopProxy) constructor.newInstance(advisedSupport);
// 调用getProxy方法创建代理对象
MyService myService = (MyService) aopProxy.getProxy();
// 输出代理对象的信息
System.out.println("Cglib Class = " + myService.getClass());
// 调用代理对象的方法
System.out.println("doSomething method result = " + myService.doSomething());
}
}
```
运行结果,代理对象的类为 `com.xcs.spring.MyServiceImpl$$EnhancerBySpringCGLIB$$3c231008`,调用代理对象的 `doSomething` 方法结果为 `"hello world"`。
```java
Cglib Class = class com.xcs.spring.MyServiceImpl$$EnhancerBySpringCGLIB$$3c231008
doSomething method result = hello world
```
### 七、时序图
#### JdkDynamicAopProxy
~~~mermaid
sequenceDiagram
autonumber
AopProxyDemo->>JdkDynamicAopProxy:new JdkDynamicAopProxy()
JdkDynamicAopProxy->>JdkDynamicAopProxy:this.advised
JdkDynamicAopProxy->>JdkDynamicAopProxy:this.proxiedInterfaces
JdkDynamicAopProxy->>AopProxyDemo:返回aopProxy
AopProxyDemo->>JdkDynamicAopProxy:aopProxy.getProxy()
JdkDynamicAopProxy->>JdkDynamicAopProxy:getProxy(classLoader)
JdkDynamicAopProxy->>Proxy:Proxy.newProxyInstance()
JdkDynamicAopProxy->>AopProxyDemo:返回代理对象
AopProxyDemo->>$Proxy0:aopProxy.doSomething()
$Proxy0->>JdkDynamicAopProxy:invoke()
alt 不存在拦截链
rect rgb(122,197,205)
JdkDynamicAopProxy->>AopUtils: invokeJoinpointUsingReflection()
AopUtils->>Method:method.invoke(target, args)
Method->>$Proxy0:doSomething()
end
else 存在拦截链
rect rgb(155,205,155)
JdkDynamicAopProxy->>ReflectiveMethodInvocation:new ReflectiveMethodInvocation()
ReflectiveMethodInvocation->>JdkDynamicAopProxy:返回invocation
JdkDynamicAopProxy->>ReflectiveMethodInvocation:invocation.proceed()
ReflectiveMethodInvocation->>ReflectiveMethodInvocation:invokeJoinpoint()
ReflectiveMethodInvocation->>AopUtils:invokeJoinpointUsingReflection()
AopUtils->>Method:method.invoke(target, args)
Method->>$Proxy0:doSomething()
end
end
~~~
#### CglibAopProxy
~~~mermaid
sequenceDiagram
autonumber
AopProxyDemo->>CglibAopProxy:new CglibAopProxy()
CglibAopProxy->>CglibAopProxy:this.advised
CglibAopProxy->>CglibAopProxy:this.advisedDispatcher
CglibAopProxy->>AopProxyDemo:返回aopProxy
AopProxyDemo->>CglibAopProxy:aopProxy.getProxy()
CglibAopProxy->>CglibAopProxy:getProxy(classLoader)
CglibAopProxy->>Enhancer:new Enhancer()
Enhancer->>CglibAopProxy:返回enhancer
CglibAopProxy->>CglibAopProxy:getCallbacks()
CglibAopProxy->>CglibAopProxy:createProxyClassAndInstance()
CglibAopProxy->>Enhancer:enhancer.create()
CglibAopProxy->>AopProxyDemo:返回代理对象
AopProxyDemo->>MyServiceImpl$$EnhancerBySpringCGLIB$$:aopProxy.doSomething()
MyServiceImpl$$EnhancerBySpringCGLIB$$->>DynamicAdvisedInterceptor:intercept()
alt 不存在拦截链
rect rgb(122,197,205)
DynamicAdvisedInterceptor->>MethodProxy:this.methodProxy.invoke()
MethodProxy->>MyServiceImpl$$EnhancerBySpringCGLIB$$:doSomething()
end
else 存在拦截链
rect rgb(155,205,155)
DynamicAdvisedInterceptor->>CglibMethodInvocation:new CglibMethodInvocation()
MethodProxy->>CglibMethodInvocation:传递methodProxy
CglibMethodInvocation->>CglibMethodInvocation:接收methodProxy
CglibMethodInvocation->>DynamicAdvisedInterceptor:返回invocation
DynamicAdvisedInterceptor->>CglibMethodInvocation:invocation.proceed()
CglibMethodInvocation->>ReflectiveMethodInvocation:super.proceed()
ReflectiveMethodInvocation->>CglibMethodInvocation:invokeJoinpoint()
CglibMethodInvocation->>MethodProxy:this.methodProxy.invoke()
MethodProxy->>MyServiceImpl$$EnhancerBySpringCGLIB$$:doSomething()
end
end
~~~
### 七、源码分析
#### JdkDynamicAopProxy
在`org.springframework.aop.framework.JdkDynamicAopProxy#getProxy()`方法中,主要作用是返回一个代理对象,使用默认的类加载器来生成代理。
```java
@Override
public Object getProxy() {
return getProxy(ClassUtils.getDefaultClassLoader());
}
```
在`org.springframework.aop.framework.JdkDynamicAopProxy#getProxy(java.lang.ClassLoader)`方法中,接收一个类加载器作为参数,并根据传入的类加载器和被代理的接口数组来创建一个 JDK 动态代理对象。
```java
@Override
public Object getProxy(@Nullable ClassLoader classLoader) {
if (logger.isTraceEnabled()) {
logger.trace("Creating JDK dynamic proxy: " + this.advised.getTargetSource());
}
return Proxy.newProxyInstance(classLoader, this.proxiedInterfaces, this);
}
```
在`org.springframework.aop.framework.JdkDynamicAopProxy#invoke`方法中,`JdkDynamicAopProxy`实现了`InvocationHandler`接口,因此可以执行`invoke`方法。在方法中,首先根据方法是否为`equals`或`hashCode`方法进行特殊处理,然后获取目标对象并获取拦截器链。接着,根据拦截器链是否为空,选择直接调用目标对象方法或者通过方法拦截器链依次执行。最后,根据方法的返回值类型进行处理,如果返回值为目标对象并且返回类型与代理类型相同,则将返回值修改为代理对象。在方法执行完毕后,确保释放目标对象并恢复旧的代理对象。
```java
/**
* 实现了 {@code InvocationHandler.invoke} 方法。
*
调用者将看到目标对象抛出的异常,除非一个钩子方法抛出异常。
*/
@Override
@Nullable
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 旧的代理对象
Object oldProxy = null;
// 是否设置了代理上下文标志
boolean setProxyContext = false;
// 目标源
TargetSource targetSource = this.advised.targetSource;
// 目标对象
Object target = null;
try {
if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {
// 目标对象未实现 equals(Object) 方法
return equals(args[0]);
} else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
// 目标对象未实现 hashCode() 方法
return hashCode();
} else if (method.getDeclaringClass() == DecoratingProxy.class) {
// 只有 getDecoratedClass() 声明 -> 转发到代理配置
return AopProxyUtils.ultimateTargetClass(this.advised);
} else if (!this.advised.opaque && method.getDeclaringClass().isInterface() &&
method.getDeclaringClass().isAssignableFrom(Advised.class)) {
// 在代理配置上执行服务调用...
return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);
}
Object retVal;
if (this.advised.exposeProxy) {
// 必要时使调用可用
oldProxy = AopContext.setCurrentProxy(proxy);
setProxyContext = true;
}
// 尽可能晚地获取目标对象,以最小化我们“拥有”目标对象的时间,以防它来自池。
target = targetSource.getTarget();
Class> targetClass = (target != null ? target.getClass() : null);
// 获取此方法的拦截器链。
List