代理模式
创建时间:
0x00 代理模式
代理模式(Proxy Pattern)是一种结构型设计模式,它为其他对象提供一个代理以控制对这个对象的访问。代理模式的主要目的是在不直接暴露目标对象的情况下,通过代理对象来间接地操作目标对象。这样做的好处是可以增加额外的功能,比如权限检查、缓存、日志记录等,而不会修改原始对象的行为。
在 Java 中,代理模式可以通过多种方式实现,包括静态代理、动态代理(JDK 动态代理)和 CGLIB 动态代理。下面我们来分别介绍这些实现方式。
类图:
classDiagram
class Subject {
+request()
}
class RealSubject {
+request()
}
class ProxySubject {
+request()
}
class Client {
+main()
}
Subject <|-- "实现" RealSubject
Subject <|-- "实现" ProxySubject
RealSubject o-- "聚合" ProxySubject
Client ..> ProxySubject
0x01 静态代理
静态代理是最简单的代理模式实现,它要求我们手动创建代理类,并且需要知道目标对象的接口。下面是一个简单的静态代理的例子:
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
| interface Subject { void request(); }
class RealSubject implements Subject { @Override public void request() { System.out.println("RealSubject: Handling request."); } }
class ProxySubject implements Subject { private RealSubject realSubject;
public ProxySubject(RealSubject realSubject) { this.realSubject = realSubject; }
@Override public void request() { System.out.println("Proxy: Before request."); realSubject.request(); System.out.println("Proxy: After request."); } }
public class Client { public static void main(String[] args) { RealSubject realSubject = new RealSubject(); Subject proxy = new ProxySubject(realSubject); proxy.request(); } }
|
0x02 JDK 动态代理
JDK 动态代理允许我们在运行时动态地创建一个代理对象。为了使用 JDK 动态代理,我们需要实现 InvocationHandler 接口,并使用 Proxy.newProxyInstance() 方法来创建代理对象。下面是一个使用 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 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
| import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy;
interface Subject { void request(); }
class RealSubject implements Subject { @Override public void request() { System.out.println("RealSubject: Handling request."); } }
class DynamicProxy implements InvocationHandler { private Object target;
public DynamicProxy(Object target) { this.target = target; }
@Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("DynamicProxy: Before request."); Object result = method.invoke(target, args); System.out.println("DynamicProxy: After request."); return result; }
public Subject getProxy() { return (Subject) Proxy.newProxyInstance( target.getClass().getClassLoader(), target.getClass().getInterfaces(), this); } }
public class Client { public static void main(String[] args) { RealSubject realSubject = new RealSubject(); Subject proxy = new DynamicProxy(realSubject).getProxy(); proxy.request(); } }
|
0x03 CGLIB 动态代理
CGLIB 是一个高性能的代码生成库,它可以被用来动态地创建代理对象,即使目标对象没有实现任何接口。CGLIB 通过继承的方式实现动态代理,因此它可以代理那些没有实现接口的类。下面是使用 CGLIB 创建代理的一个例子:
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
| import net.sf.cglib.proxy.Enhancer; import net.sf.cglib.proxy.MethodInterceptor; import net.sf.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
class RealSubject { public void request() { System.out.println("RealSubject: Handling request."); } }
class CglibProxy implements MethodInterceptor { private Object target;
public CglibProxy(Object target) { this.target = target; }
public Object getProxy() { Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(target.getClass()); enhancer.setCallback(this); return enhancer.create(); }
@Override public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable { System.out.println("CglibProxy: Before request."); Object result = methodProxy.invokeSuper(proxy, args); System.out.println("CglibProxy: After request."); return result; } }
public class Client { public static void main(String[] args) { RealSubject realSubject = new RealSubject(); RealSubject proxy = (RealSubject) new CglibProxy(realSubject).getProxy(); proxy.request(); } }
|
0x04 对比装饰者模式
代理模式vs装饰器模式
文章标题:代理模式
本文作者:zhu8fei
发布时间:2024-08-15, 16:57:52
最后更新:2024-08-16, 18:17:58
原始链接:http://www.zhu8fei.com/2024/08/15/proxy-pattern.html
版权声明: "署名-非商用-相同方式共享 4.0" 转载请保留原文链接及作者。