spring 14 jdk 和 cglib 的统一
Spring 中对切点、通知、切面的抽象如下
- 切点:接口 Pointcut,典型实现 AspectJExpressionPointcut
- 通知:典型接口为 MethodInterceptor 代表环绕通知
- 切面:Advisor,包含一个 Advice 通知,PointcutAdvisor 包含一个 Advice 通知和一个 Pointcut
classDiagram
class Advice
class MethodInterceptor
class Advisor
class PointcutAdvisor
Pointcut <|-- AspectJExpressionPointcut
Advice <|-- MethodInterceptor
Advisor <|-- PointcutAdvisor
PointcutAdvisor o-- "一" Pointcut
PointcutAdvisor o-- "一" Advice
<<interface>> Advice
<<interface>> MethodInterceptor
<<interface>> Pointcut
<<interface>> Advisor
<<interface>> PointcutAdvisor
代理相关类图
- AopProxyFactory 根据 proxyTargetClass 等设置选择 AopProxy 实现
- AopProxy 通过 getProxy 创建代理对象
- 图中 Proxy 都实现了 Advised 接口,能够获得关联的切面集合与目标(其实是从 ProxyFactory 取得)
- 调用代理方法时,会借助 ProxyFactory 将通知统一转为环绕通知:MethodInterceptor
classDiagram
Advised <|-- ProxyFactory
ProxyFactory o-- Target
ProxyFactory o-- "多" Advisor
ProxyFactory --> AopProxyFactory : 使用
AopProxyFactory --> AopProxy
Advised <|-- 基于CGLIB的Proxy
基于CGLIB的Proxy <-- ObjenesisCglibAopProxy : 创建
AopProxy <|-- ObjenesisCglibAopProxy
AopProxy <|-- JdkDynamicAopProxy
基于JDK的Proxy <-- JdkDynamicAopProxy : 创建
Advised <|-- 基于JDK的Proxy
class AopProxy {
+getProxy() Object
}
class ProxyFactory {
proxyTargetClass : boolean
}
class ObjenesisCglibAopProxy {
advised : ProxyFactory
}
class JdkDynamicAopProxy {
advised : ProxyFactory
}
<<interface>> Advised
<<interface>> AopProxyFactory
<<interface>> AopProxy
底层切点、通知、切面
模拟
import org.aopalliance.intercept.MethodInterceptor;
import org.springframework.aop.aspectj.AspectJExpressionPointcut;
import org.springframework.aop.framework.ProxyFactory;
import org.springframework.aop.support.DefaultPointcutAdvisor;
public class S14 {
public static void main(String[] args) {
testSpringProxy1();
}
private static void testSpringProxy1() {
//定义切点 pointcut
AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();
pointcut.setExpression("execution(* cn.xyf.spring.s14.*.a(..))");
//定义通知 advice
MethodInterceptor advice = invocation -> {
System.out.println("前置增强...");
Object result = invocation.proceed();
System.out.println("后置增强...");
return result;
};
//定义切面 advisor
DefaultPointcutAdvisor advisor = new DefaultPointcutAdvisor(pointcut, advice);
//使用工厂创建代理
// * 如果指定了接口,且 proxyTargetClass = false,使用 JdkDynamicAopProxy
// * 如果没有指定接口,或者 proxyTargetClass = true,使用 ObjenesisCglibAopProxy
// * 例外:如果目标是接口类型或已经是 Jdk 代理,使用 JdkDynamicAopProxy
S14Bean2 target = new S14Bean2();
ProxyFactory proxyFactory = new ProxyFactory();
proxyFactory.setInterfaces(target.getClass().getInterfaces());
proxyFactory.setProxyTargetClass(true);
proxyFactory.setTarget(target);
proxyFactory.addAdvisor(advisor);
S14Bean1 proxy = (S14Bean1) proxyFactory.getProxy();
System.out.println(proxy.getClass());
proxy.a();
proxy.b();
}
}
class S14Bean2 implements S14Bean1{
@Override
public void a() {
System.out.println("S14Bean2 a running...");
}
public void a(int i) {
System.out.println("S14Bean2 a running" + i);
}
@Override
public void b() {
System.out.println("S14Bean2 b running...");
}
}
interface S14Bean1 {
void a();
void b();
}
- 底层的切点实现
- 底层的通知实现
- 底层的切面实现
- ProxyFactory 用来创建代理
- 如果指定了接口,且 proxyTargetClass = false,使用 JdkDynamicAopProxy
- 如果没有指定接口,或者 proxyTargetClass = true,使用 ObjenesisCglibAopProxy
- 例外:如果目标是接口类型或已经是 Jdk 代理,使用 JdkDynamicAopProxy
注意
- 要区分本章节提到的 MethodInterceptor,它与之前 cglib 中用的的 MethodInterceptor 是不同的接口