简介

在 Java 中,代理(Proxy)模式是一种设计模式,它允许你为对象提供一个替身或占位符,以控制对该对象的访问。代理模式可以用于各种场景,比如延迟加载、访问控制、日志记录、事务处理等。

Java 中有两种常见的代理方式:

  • 静态代理
  • 动态代理

静态代理

静态代理类在编译期间就已经确定,需要手动编写代理类,通常,静态代理类实现与被代理对象相同的接口,并且在代理类中可以对方法的调用进行增强处理。

在下面的例子中,ServiceProxy 是 RealService 的代理,它在调用 performAction 方法之前和之后做了一些额外的工作。

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
32
33
34
35
36
// 定义接口
public interface Service {
void performAction();
}

// 实现接口的真实对象
public class RealService implements Service {
@Override
public void performAction() {
System.out.println("Performing action in RealService");
}
}

// 代理类
public class ServiceProxy implements Service {
private Service realService;

public ServiceProxy(Service realService) {
this.realService = realService;
}

@Override
public void performAction() {
System.out.println("Proxy before action");
realService.performAction(); // 调用真实对象的方法
System.out.println("Proxy after action");
}
}

// 测试
public class Main {
public static void main(String[] args) {
Service service = new ServiceProxy(new RealService());
service.performAction();
}
}

动态代理

Java 的动态代理是在运行时生成代理类。Java 提供了两种动态代理的方式:

  • JDK 动态代理:用于代理实现了接口的类。
  • CGLIB 动态代理:用于代理没有实现接口的类。

JDK 动态代理

JDK 动态代理依赖于 java.lang.reflect.Proxy 类和 InvocationHandler 接口。

在这个示例中,Proxy.newProxyInstance 方法用于动态创建一个代理对象。通过 InvocationHandler 接口的 invoke 方法,可以在调用真实对象的方法之前或之后执行一些额外操作。

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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

// 定义接口
public interface Service {
void performAction();
}

// 实现接口的真实对象
public class RealService implements Service{
@Override
public void performAction() {
System.out.println("Performing action in RealService");
}
}

// 动态代理类
public class ServiceInvocationHandler implements InvocationHandler {
private Object target;

public ServiceInvocationHandler(Object target) {
this.target = target;
}

@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("Proxy before action");
Object result = method.invoke(target, args); // 调用真实对象的方法
System.out.println("Proxy after action");
return result;
}
}

// 测试
public class Main {
public static void main(String[] args) {
Service realService = new RealService();
Service proxyService = (Service) Proxy.newProxyInstance(
realService.getClass().getClassLoader(),
new Class[]{Service.class},
new ServiceInvocationHandler(realService)
);
proxyService.performAction();
}
}

CGLIB 动态代理

CGLIB 动态代理不要求目标类实现接口,它通过继承目标类来创建代理对象。CGLIB 常用于没有实现接口的类的代理。
需要注意,JDK 动态代理只能代理实现了接口的类,而 CGLIB 可以代理没有接口的类。