Java中的代理模式(Proxy Pattern)是一种结构型设计模式,它为其他对象提供一种代理以控制对这个对象的访问。通过这种方式,我们可以在不修改原始类代码的情况下,增加额外的功能,比如权限控制、日志记录、事务处理等。代理模式主要分为静态代理和动态代理两种。
1,静态代理
静态代理是指代理类在程序运行前就已经被定义好了,它直接由程序员编写,与原始类的对应关系在编译时就确定了。
// 接口
interface Subject {
void request();
}
// 真实对象
class RealSubject implements Subject {
@Override
public void request() {
System.out.println("访问真实对象方法");
}
}
// 代理对象
class ProxySubject implements Subject {
private RealSubject realSubject;
public ProxySubject(RealSubject realSubject) {
this.realSubject = realSubject;
}
@Override
public void request() {
// 在调用真实对象的方法前后添加额外功能
preRequest();
realSubject.request();
postRequest();
}
private void preRequest() {
//....
System.out.println("调用真实对象前可以添加的功能");
//....
}
private void postRequest() {
//....
System.out.println("调用真实对象后可以添加的功能");
//....
}
}
// 测试类
public class TestProxy {
public static void main(String[] args) {
RealSubject realSubject = new RealSubject();
ProxySubject proxySubject = new ProxySubject(realSubject);
proxySubject.request();
}
}
动态代理
动态代理是在运行时动态生成代理类的,它不需要我们手动编写代理类代码。Java中主要通过java.lang.reflect.Proxy
类和java.lang.reflect.InvocationHandler
接口来实现动态代理。动态代理通常用于接口代理,如果要代理类(非接口),则需要使用第三方库如CGLIB。
// 接口
interface Subject {
void request();
}
// 真实对象
class RealSubject implements Subject {
@Override
public void request() {
System.out.println("访问真实对象方法");
}
}
// 调用处理器
class InvocationHandlerImpl implements InvocationHandler {
private Object target;
public InvocationHandlerImpl(Object target) {
this.target = target;
}
@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;
}
// 获取动态代理对象
public static Object getProxyInstance(Object target, Class<?>... interfaces) {
return Proxy.newProxyInstance(
target.getClass().getClassLoader(),
interfaces,
new InvocationHandlerImpl(target)
);
}
}
// 测试类
public class TestDynamicProxy {
public static void main(String[] args) {
RealSubject realSubject = new RealSubject();
Subject proxySubject = (Subject) InvocationHandlerImpl.getProxyInstance(realSubject, Subject.class);
proxySubject.request();
}
}