Java中的代理对象

​ 在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");
}
}