动态代理模式可以增强方法,在不改变原来方法的基础上添加我们自己的逻辑代码,例如添加日志,权限等。
public interface Sell { void sell(); void ad(); } public class Vendor implements Sell { @Override public void sell() { System.out.println("Shop sell goods"); } @Override public void ad() { System.out.println("Shop advert goods"); } } public interface InvocationHandler { Object invoke(Object proxy, Method method, Object[] args) throws Throwable; } public class LogHandler implements java.lang.reflect.InvocationHandler { Object target; // 被代理的对象,实际的方法执行者 public LogHandler(Object target) { this.target = target; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { before(); Object result = method.invoke(target, args); // 调用 target 的 method 方法 after(); return result; // 返回方法的执行结果 } // 调用invoke方法之前执行 private void before() { System.out.println(String.format("log start time [%s] ", new Date())); } // 调用invoke方法之后执行 private void after() { System.out.println(String.format("log end time [%s] ", new Date())); } } public class DynamicProxyMain { public static void main(String[] args) { // 创建中介类实例 LogHandler logHandler = new LogHandler(new Vendor()); // 设置该变量可以保存动态代理类,默认名称$Proxy0.class System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles", "true"); // 获取代理类实例Sell Sell sell = (Sell) (Proxy.newProxyInstance(Vendor.class.getClassLoader(), new Class[]{Sell.class}, logHandler)); // 通过代理类对象调用代理类方法,实际上会转到invoke方法调用 sell.sell(); // sell.ad(); } }
注意:动态代理中invoke方法中的proxy对象其实是$Proxy0,这个才是真正的代理类,main方法中sell.sell()其实调用的是$Proxy0中的sell()方法。
sell()方法又调用的是LogHandler中的invoke方法,所以这就是为什么调用方法时为什么会调用invoke()方法。
$Proxy0类如下:
// // Source code recreated from a .class file by IntelliJ IDEA // (powered by Fernflower decompiler) // package com.sun.proxy; import com.jjy.modules.model.stock.Sell; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; import java.lang.reflect.UndeclaredThrowableException; public final class $Proxy0 extends Proxy implements Sell { private static Method m1; private static Method m2; private static Method m4; private static Method m3; private static Method m0; public $Proxy0(InvocationHandler var1) throws { super(var1); } public final boolean equals(Object var1) throws { try { return (Boolean)super.h.invoke(this, m1, new Object[]{var1}); } catch (RuntimeException | Error var3) { throw var3; } catch (Throwable var4) { throw new UndeclaredThrowableException(var4); } } public final String toString() throws { try { return (String)super.h.invoke(this, m2, (Object[])null); } catch (RuntimeException | Error var2) { throw var2; } catch (Throwable var3) { throw new UndeclaredThrowableException(var3); } } public final void ad() throws { try { super.h.invoke(this, m4, (Object[])null); } catch (RuntimeException | Error var2) { throw var2; } catch (Throwable var3) { throw new UndeclaredThrowableException(var3); } } public final void sell() throws { try { super.h.invoke(this, m3, (Object[])null); } catch (RuntimeException | Error var2) { throw var2; } catch (Throwable var3) { throw new UndeclaredThrowableException(var3); } } public final int hashCode() throws { try { return (Integer)super.h.invoke(this, m0, (Object[])null); } catch (RuntimeException | Error var2) { throw var2; } catch (Throwable var3) { throw new UndeclaredThrowableException(var3); } } static { try { m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object")); m2 = Class.forName("java.lang.Object").getMethod("toString"); m4 = Class.forName("com.jjy.modules.model.stock.Sell").getMethod("ad"); m3 = Class.forName("com.jjy.modules.model.stock.Sell").getMethod("sell"); m0 = Class.forName("java.lang.Object").getMethod("hashCode"); } catch (NoSuchMethodException var2) { throw new NoSuchMethodError(var2.getMessage()); } catch (ClassNotFoundException var3) { throw new NoClassDefFoundError(var3.getMessage()); } } }