在代理模式中,一个代理对象控制对另一个对象的访问。代理可以在访问目标对象时添加额外的操作,例如日志记录、权限检查、延迟加载等。
代理模式有两种常见的实现方式:
Java 中的动态代理主要有两种实现方式:
java.lang.reflect.Proxy
类和 InvocationHandler
接口,只能代理实现了接口的类。JDK 动态代理是通过 Proxy
类和 InvocationHandler
接口来实现的。它只能代理实现了接口的类。
关键组件:
InvocationHandler
接口:定义了 invoke
方法,代理对象的所有方法调用都会被转发到这个方法中。Proxy
类:提供了创建代理对象的静态方法 newProxyInstance
。示例:
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
// 定义一个接口
interface MyService {
void doSomething();
}
// 实现接口的具体类
class MyServiceImpl implements MyService {
@Override
public void doSomething() {
System.out.println("Doing something in MyServiceImpl");
}
}
// 自定义 InvocationHandler
class MyInvocationHandler implements InvocationHandler {
private final Object target;
public MyInvocationHandler(Object target) {
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("Before method: " + method.getName());
Object result = method.invoke(target, args); // 调用目标对象的方法
System.out.println("After method: " + method.getName());
return result;
}
}
public class DynamicProxyExample {
public static void main(String[] args) {
// 创建目标对象
MyService target = new MyServiceImpl();
// 创建代理对象
MyService proxy = (MyService) Proxy.newProxyInstance(
target.getClass().getClassLoader(),
target.getClass().getInterfaces(),
new MyInvocationHandler(target)
);
// 调用代理对象的方法
proxy.doSomething();
}
}
输出:
Before method: doSomething
Doing something in MyServiceImpl
After method: doSomething
步骤解析:
MyService
和其实现类 MyServiceImpl
。InvocationHandler
:实现 InvocationHandler
接口,并在 invoke
方法中增加额外的操作(如方法前后的日志打印)。Proxy.newProxyInstance
创建代理对象,传入目标对象的类加载器、接口列表和自定义的 InvocationHandler
。InvocationHandler
中的 invoke
方法会被触发,执行额外操作后,再调用目标对象的方法。CGLIB 动态代理基于生成目标类的子类进行代理,因此可以代理没有实现接口的类。CGLIB 在 Spring 中也被广泛使用,特别是用来代理非接口类。
CGLIB 代理的简单示例(使用 Maven 引入 CGLIB 依赖):
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>3.3.0</version>
</dependency>
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
// 定义一个普通类
class MyClass {
public void doSomething() {
System.out.println("Doing something in MyClass");
}
}
// 自定义 MethodInterceptor
class MyMethodInterceptor implements MethodInterceptor {
@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
System.out.println("Before method: " + method.getName());
Object result = proxy.invokeSuper(obj, args); // 调用父类的方法
System.out.println("After method: " + method.getName());
return result;
}
}
public class CglibProxyExample {
public static void main(String[] args) {
// 创建 Enhancer 对象
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(MyClass.class);
enhancer.setCallback(new MyMethodInterceptor());
// 创建代理对象
MyClass proxy = (MyClass) enhancer.create();
proxy.doSomething();
}
}
输出:
Before method: doSomething
Doing something in MyClass
After method: doSomething
注意:
final
,CGLIB 代理无法创建代理对象,因为它不能继承 final
类。Proxy
和 InvocationHandler
实现,简单灵活。