AOP代理机制
Spring AOP通过动态代理将横切逻辑织入目标对象,核心有两种代理方式。
代理类型对比
| 特性 | JDK动态代理 | CGLIB代理 |
|---|---|---|
| 原理 | 基于接口,反射机制 | 基于继承,字节码增强 |
| 条件 | 目标类实现接口 | 目标类可被继承 |
| 性能 | 调用稍慢,生成快 | 调用快,生成稍慢 |
| 限制 | 只能代理接口方法 | 不能代理final类和方法 |
JDK动态代理
Java
// 目标接口
public interface UserService {
void save();
}
// 目标类
public class UserServiceImpl implements UserService {
public void save() {
System.out.println("保存用户");
}
}
// JDK代理工厂
public class JdkProxyFactory implements InvocationHandler {
private Object target;
public Object getProxy(Object target) {
this.target = target;
return Proxy.newProxyInstance(
target.getClass().getClassLoader(),
target.getClass().getInterfaces(),
this
);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
System.out.println("前置通知");
Object result = method.invoke(target, args);
System.out.println("后置通知");
return result;
}
}
CGLIB代理
Java
// 目标类(无需接口)
public class OrderService {
public void create() {
System.out.println("创建订单");
}
}
// CGLIB代理工厂
public class CglibProxyFactory implements MethodInterceptor {
private Object target;
public Object getProxy(Object target) {
this.target = target;
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(target.getClass());
enhancer.setCallback(this);
return enhancer.create();
}
@Override
public Object intercept(Object obj, Method method, Object[] args,
MethodProxy proxy) throws Throwable {
System.out.println("前置通知");
Object result = method.invoke(target, args);
System.out.println("后置通知");
return result;
}
}
Spring AOP代理策略
Java
// Spring默认策略
@Configuration
@EnableAspectJAutoProxy
public class AopConfig {
// proxyTargetClass = true 强制使用CGLIB
// proxyTargetClass = false 智能选择(默认)
}
// 注解方式强制CGLIB
@EnableAspectJAutoProxy(proxyTargetClass = true)
// XML配置
<aop:aspectj-autoproxy proxy-target-class="true"/>
Spring Boot 2.x后默认
proxyTargetClass=true,优先使用CGLIB。
要点总结
- JDK动态代理基于接口,CGLIB基于继承
- 目标类无接口时自动使用CGLIB
proxyTargetClass=true强制使用CGLIB- final类和方法无法被CGLIB代理
- Spring Boot 2.x默认CGLIB代理
📝 发现内容有误?点击此处直接编辑