先上代码,怎么使用jdk的动态代理。
定义一个接口,UserService,里面有add方法
定义一个类实现UserService
测试类
public interface UserService { void add(); } =========== public class UserServImp implements UserService { @Override public void add() { System.out.println("add"); } } ======== import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; public class Test2 { public static void main(String[] args) { UserService serv = new UserServImp(); UserService servProxy = (UserService) Proxy.newProxyInstance(serv.getClass().getClassLoader(), serv.getClass().getInterfaces(), new InvocationHandler() { @Override //参数解释 proxy 真实的那个代理对象 method方法对象 args 方法的参数 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("------"); return method.invoke(serv, args); } }); servProxy.add(); } }
最后执行结果如下
接下来简单说说原理,
当我们调用代理类的方法的时候,代理类会把自己(反编译源代码发现),方法,参数 传递给 handler ,handler 会执行invoke方法。
所以当我们每调用一次代理的方法,都会走handler
细心的朋友可能会发现 原始类和代理类的hashcode一致,如下图所示
之所以相等是因为都是调用原来的对象的hashcode方法,但其实是不同的对象哈。
注意:
默认jdk不会把代理类字节码生成到本地文件系统
需要配置 System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");
然后可以在你的项目comsunproxy 目录找到到该代理类的字节码 (jdk8会自动创建目录,jdk7好像不会 需要手动创建该目录)
使用反编译(eg:jd-gui)即可查看
原理解说看这里 jdk动态代理原理