为其他对象提供一种代理以控制对这个对象的访问。 在某些情况下,一个对象不适合或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用 代理模式的例子:指针引用代理
代理分静态代理和动态代理
静态代理没有利用反射,编译时就确定了类以及方法构成,导致静态代理只能对某一个接口进行代理,且代码重复较大,适合某些特定业务类的代理。
动态代理利用了反射,运行时才调用代理逻辑,可以对所有接口代理,代理简洁。适合通用类的额外功能代理,比如打印日志、切入事务等。
具体代码如下:
subject接口代码:
package com.draco.base.java.designmode.proxy; public interface Subject { void request(); void hello(); }
subject业务实现类代码:
public class RealSubject implements Subject{ public void request() { System.out.println(this.getClass().getName()+" request ..."); } @Override public void hello() { System.out.println(this.getClass().getName()+" hello ..."); } }
静态代理类代码:
public class StaticProxy implements Subject { private Subject subject; public StaticProxy(Subject subject){ this.subject = subject; } @Override public void request() { printLog(); subject.request(); } @Override public void hello() { printLog(); subject.hello(); } private void printLog(){ System.out.println(this.getClass().getName()+"为["+subject.getClass().getName()+"]打印日志"); } }
动态代理类代码:
package com.draco.base.java.designmode.proxy; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; public class DynamicProxy implements InvocationHandler { private Object targetClass; public Object getInstance(Object targetClass){ this.targetClass = targetClass; return Proxy.newProxyInstance(targetClass.getClass().getClassLoader(),targetClass.getClass().getInterfaces(),this); } //代理的类方法被调用时将会执行这个invoke方法 @Override public Object invoke(Object proxy, Method method, Object[] args) { printLog(); Object ret = null; try { //执行目标类的真正业务方法 ret = method.invoke(targetClass,args); } catch (Exception e) { System.out.println("调用方法失败!"); e.printStackTrace(); } return ret; } private void printLog(){ System.out.println(this.getClass().getName()+"为["+targetClass.getClass().getName()+"]打印日志"); } }
测试应用类代码:
public class ProxyApplication { public static void main(String[] args) { Subject proxy = new StaticProxy(new RealSubject()); proxy.request(); System.out.println("---------------------"); Subject proxy2 = (Subject)new DynamicProxy().getInstance(new RealSubject()); proxy2.request(); System.out.println("---------------------"); Subject subject = new RealSubject(); subject.request(); } }
具体打印信息如下: