在java中,我们用到的代理主要有两种:静态代理、动态代理。静态代理相对比较简单易懂,逻辑清晰;而动态代理逻辑就比较绕,比较复杂。相对的,一得一失,静态代理代码冗余不够灵活,而动态代理的代码就比较灵活方便。
特性 |
静态代理 |
动态代理 |
代理类生成时间 |
编译期写死 |
运行时动态生成 |
开发成本 |
高(每个接口都要写代理类) |
低(统一写 InvocationHandler / MethodInterceptor) |
灵活性 |
低 |
高 |
性能 |
较高(无反射) |
稍低(有反射/字节码增强) |
使用场景 |
代理对象少,结构简单 |
需要通用代理、AOP 框架(Spring) |
静态代理
写法:需要在代码里手动编写一个代理类,代理类和目标类实现同一个接口。
特点:
- 编译期确定代理关系。
- 代理类是提前写好的,结构固定。
- 每增加一个接口或方法,都需要手动维护代理类,扩展性差。
优点:逻辑清晰,性能开销小(没有反射)。
缺点:代码冗余严重,不灵活。
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 interface UserService { void addUser(String name); }
public class UserServiceImpl implements UserService { public void addUser(String name) { System.out.println("添加用户: " + name); } }
public class UserServiceProxy implements UserService { private UserService target; public UserServiceProxy(UserService target) { this.target = target; } @Override public void addUser(String name) { System.out.println("前置处理"); target.addUser(name); System.out.println("后置处理"); } }
public class Main { public static void main(String[] args) { UserService service = new UserServiceProxy(new UserServiceImpl()); service.addUser("张三"); } }
|
动态代理
写法:在运行时动态生成代理类,不需要提前写死。
- JDK 动态代理:基于接口 +
InvocationHandler
+ 反射。
- CGLIB 动态代理:基于字节码生成(子类继承目标类)。
特点:
- 运行期确定代理关系。
- 不需要手动写代理类,灵活。
- 依赖反射或字节码增强,性能比静态代理稍弱(但现代 JVM 优化后差距不大)。
优点:通用性强,减少代码冗余。
缺点:调试困难,可能有性能损耗。
动态代理分为两类:JDK动态代理、CGLIB动态代理
特性 |
JDK 动态代理 |
CGLIB 代理 |
代理对象 |
接口的实现类 |
目标类的子类 |
是否需要接口 |
必须有接口 |
不需要接口 |
底层实现 |
反射(Proxy + InvocationHandler) |
字节码增强(ASM + MethodInterceptor) |
性能 |
JDK 1.8 之前略慢,之后优化较好 |
一般比反射快,但生成类开销大 |
限制 |
只能代理接口方法 |
不能代理 final 类/方法 |
JDK动态代理
接口 & 实现类
1 2 3 4 5 6 7 8 9 10
| public interface UserService { void addUser(String name); }
public class UserServiceImpl implements UserService { @Override public void addUser(String name) { System.out.println("添加用户: " + name); } }
|
JDK 动态代理实现
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
| import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy;
public class JdkProxyDemo { public static void main(String[] args) { UserService target = new UserServiceImpl();
UserService proxy = (UserService) Proxy.newProxyInstance( target.getClass().getClassLoader(), new Class[]{UserService.class}, new InvocationHandler() { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("[JDK代理] 调用方法前: " + method.getName()); Object result = method.invoke(target, args); System.out.println("[JDK代理] 调用方法后: " + method.getName()); return result; } } );
proxy.addUser("张三"); } }
|
CGLIB动态代理
目标类(没有接口)
1 2 3 4 5
| public class OrderService { public void createOrder(String orderId) { System.out.println("创建订单: " + orderId); } }
|
CGLIB 代理实现
需要引入依赖(如果是 Spring Boot 项目已经有了 spring-core
,包含 CGLIB)。
1 2 3 4 5
| <dependency> <groupId>cglib</groupId> <artifactId>cglib</artifactId> <version>3.3.0</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 26
| import net.sf.cglib.proxy.Enhancer; import net.sf.cglib.proxy.MethodInterceptor; import net.sf.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
public class CglibProxyDemo { public static void main(String[] args) { OrderService target = new OrderService();
OrderService proxy = (OrderService) Enhancer.create( OrderService.class, new MethodInterceptor() { @Override public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable { System.out.println("[CGLIB代理] 调用方法前: " + method.getName()); Object result = method.invoke(target, args); System.out.println("[CGLIB代理] 调用方法后: " + method.getName()); return result; } } );
proxy.createOrder("ORD123456"); } }
|