Class1有个doSomething方法,如果在方法执行前记录一行日志。一般的做法是,直接子doSomething方法的最前面写一行记录日志的代码。
使用代理模式,我们可以设计一个Class1Proxy,这样可以不需要更改Class1中的任何代码就能实现这个功能,如下图所示。 图 : 静态代理模式
代码实现:
public interface Class1Interface { void doSomething(); } public class Class1 implements Class1Interface { @Override public void doSomething() { System.out.println("This is Class1"); } } public class Class1Proxy implements Class1Interface { Class1 clzz = new Class1(); @Override public void doSomething() { System.out.println("Begin log"); clzz.doSomething(); System.out.println("End log"); } } public class Test { public static void main(String[] args) { Class1Proxy class1Proxy = new Class1Proxy(); class1Proxy.doSomething(); } }输出:
Begin log This is Class1 End log
每一个类都要有一个对应的Proxy类,Proxy类的数量会很多,但逻辑大同小异,称这种实现方式为“静态代理”。
参数说明:
loader,设置为目标对象class1对应的classLoader。interfaces,设置为目标对象class1所实现的接口类型,这里是Class1Interface。h:是一个实现了InvocationHandler接口的类对象,我们通过它的构造函数把目标对象class1注入。我们再去创建Class2Interface和Class2:
public interface Class2Interface { void work(); } public class Class2 implements Class2Interface { @Override public void work() { System.out.println("this is Class2"); } }自定义一个InvocationHandler,代码如下:
/** * invoke 是 InvocationHandler 接口的唯一方法 * 当我们使用动态代理调用目标对象的方法时, * 目标对象的方法会转发由InvocationHandle这个接口的invoke方法来调用 * 参数 : * 1、proxy ==> 代理的目标对象 * 2、method ==> 目标对象要调用的方法 * 3、args ==> 目标对象要调用的方法的参数数据 * */ public class MyInvocationHandler implements InvocationHandler { private Object target; public MyInvocationHandler(Object target) { this.target = target; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("Begin log"); Object obj = method.invoke(target, args); System.out.println("End log"); return obj; } }使用动态代理如下:
public class Test { public static void main(String[] args) { Test test = new Test(); test.test1(); System.out.println("-----------------------------------------"); test.test2(); } public void test1() { Class1Interface class1 = new Class1(); /** * 通过 Proxy.newProxylnstance 方法创建的对象, * 是一个实现了 Class1Interface 接口的对象, * 也就是class1Proxy 。 */ Class1Interface class1Proxy = (Class1Interface) Proxy.newProxyInstance( class1.getClass().getClassLoader(), class1.getClass().getInterfaces(), new MyInvocationHandler(class1)); /** * 执行 class1Proxy 的 doSomething 方法,其实是在执行 MyInvocationHandler类的invoke方法。 * 这个 invoke 方法是代理模式的设计思想 。 * 它有一个 method 参数,执行 method 的 invoke 方法,就是在执行 class1的 doSomething 方法 。 */ class1Proxy.doSomething(); } public void test2() { Class2Interface class2 = new Class2(); Class2Interface class2Proxy = (Class2Interface) Proxy.newProxyInstance( class2.getClass().getClassLoader(), new Class<?>[] { Class2Interface.class }, new MyInvocationHandler(class2)); class2Proxy.work(); } }输出:
Begin log This is Class1 End log ----------------------------------------- Begin log this is Class2 End log从上面可以看出,此时不需要再去创建Class2Proxy代理类。