本文共 3611 字,大约阅读时间需要 12 分钟。
代理模式是一种常见的设计模式,其核心思想是在不改变目标对象的情况下,通过引入一个间接对象(代理)来装饰或增强目标对象的功能。这种模式通常用于当我们想对目标对象的某些方法进行额外处理或监控,而不会对原始业务逻辑造成太大影响时。
在静态代理中,代理类(Proxy)与目标对象(RealObject)之间通常存在继承关系。代理类中包含一个引用(通常是通过构造器设置),这个引用指向目标对象。这样,代理类可以调用目标对象的方法,并在其中插入自己的逻辑。
interface Interface { void doSomething(); void somethingElse(String arg);}class RealObject implements Interface { @Override public void doSomething() { System.out.println("Real doSomething"); } @Override public void somethingElse(String arg) { System.out.println("Real somethingElse " + arg); }}class SimpleProxy implements Interface { private Interface proxied; public SimpleProxy(Interface proxied) { this.proxied = proxied; } @Override public void doSomething() { System.out.println("Proxy doSomething before"); proxied.doSomething(); System.out.println("Proxy doSomething after"); } @Override public void somethingElse(String arg) { System.out.println("Proxy somethingElse before"); proxied.somethingElse(arg); System.out.println("Proxy somethingElse after"); }}class SimpleProxyDemo { public static void consumer(Interface iface) { iface.doSomething(); iface.somethingElse("biu biu"); } public static void main(String[] args) { consumer(new RealObject()); // 直接调用 System.out.println(" ====== "); consumer(new SimpleProxy(new RealObject())); // 使用静态代理 }}
动态代理是一种更灵活的实现代理模式的方式。与静态代理不同,动态代理不需要预先知道目标对象的所有方法,而是在运行时动态地处理方法调用。这种方法通过反射机制实现,能够支持接口的动态扩展。
动态代理的实现依赖于两个核心组件:
InvocationHandler
接口,其主要职责是在方法调用前、执行过程中和方法调用后执行自定义逻辑。import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;import java.lang.reflect.Proxy;class DynamicProxyHandler implements InvocationHandler { private Object proxied; public DynamicProxyHandler(Object proxied) { this.proxied = proxied; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("Method: " + method.getName()); System.out.println("Arguments: " + (args != null ? args : "")); System.out.println("--- try { return method.invoke(proxied, args); } catch (Throwable e) { System.out.println("Error occurred: " + e.getMessage()); throw e; } System.out.println("After method execution"); return null; }}class SimpleDynamicProxy { public static void consumer(Interface iface) { iface.doSomething(); iface.somethingElse("biu biu"); } public static void main(String[] args) { RealObject real = new RealObject(); consumer(real); // 直接调用 System.out.println(" ============== "); // 使用动态代理生成代理对象 Interface proxy = (Interface) Proxy.newProxyInstance( Interface.class.getClassLoader(), new Class[] { Interface.class }, new DynamicProxyHandler(real) ); consumer(proxy); // 通过动态代理调用 }}
特性 | 静态代理 | 动态代理 |
---|---|---|
实现方式 | 通过直接继承接口实现 | 通过反射和InvocationHandler实现 |
方法调用控制 | 在方法体内直接添加逻辑 | 在调用处理器中动态处理方法 |
接口扩展支持 | 需要重新实现所有接口方法 | 支持接口的动态扩展 |
代理对象生成方式 | 使用构造器或工厂类 | 使用Proxy.newProxyInstance() |
性能影响 | 有一定的性能开销,但可以预先优化 | 反射操作会引入额外性能开销 |
静态代理和动态代理各有优劣,静态代理简单易懂,适合接口较为稳定和小变动的情况。动态代理则更灵活,适合接口可能发生变化或需要动态扩展功能的情况。作为开发者,根据具体需求选择合适的代理模式至关重要。
转载地址:http://kdmuk.baihongyu.com/