在面试的时候面试题里有一道jdk的动态代理是原理,并给一个事例直接写代码出来,现在再整理一下
jdk动态代理主要是想动态在代码中增加一些功能,不影响现有代码,实现动态代理需要做如下几个操作
1.首先必须要有一个接口,被代理类必须实现这个接口(必须,原因是因为生成的代理类也实现这个接口,代理完得到的类可以用这个接口类型进接收)
2.需要写一个自己的代理处理类,现在给它起个名字叫MyHandler,必须实现InvocationHandler,重写invoke方法(这个也是必须,我们要在Invoke(Object proxy, Method method, Object[] args)方法里面写自己的逻辑,调用被代理类的方法,invoke(Object proxy, Method method, Object[] args)方法里面的三个参数的意思为:代理类,被代理类的哪个方法,这个方法的参数是什么)
3.MyHandler里面必须有一个成员变量,类型为Object,可以在构造方法的时候将这个成员变量的值赋进去(这个成员变量也是必须要有的,因为在invoke方法里面需要代理这个类执行这个对象的方法)
4.得到代理对象是通过Proxy类的newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)方法得到,第一个是得到classLoader即可,第二个参数为接口,接口的数量可以多个,通过代理类可以得到:test.getClass().getInterfaces()就得到了,最后一个参数就是我们上面第2步里面自己写的代理类的实例,这样就得到了一个代理类,当然,是第一步定义的接口类型的,然后再调用得到这个对象,调用方法
代码如下,需求是在被代理类的move方法执行前后加打印语句行:
定义的接口:
public interface Inter { void move(); }
再写一个被代理类,叫ProxyClazz
1 public class ProxyClazz implements Inter{ 2 3 public void move(){ 4 System.out.println("move..."); 5 } 6 7 }
处理代理的类:
public class TestProxy implements InvocationHandler{
//被代理类,必须做为这个类的成员变量 private Object target; public TestProxy(){ super(); }
//通过构造方法传值进来 public TestProxy(Object target) { super(); this.target = target; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("start"); //查看proxy类的命名方式:com.sun.proxy.$Proxy0 System.out.println(proxy.getClass().getName()); Object o = method.invoke(target, args); System.out.println("end"); return o; } }
测试用的main方法
public static void main(String[] args) throws Exception, Throwable{ Inter inter = new ProxyClazz(); TestProxy tp = new TestProxy(inter); Inter interProxy =(Inter) Proxy.newProxyInstance(inter.getClass().getClassLoader(), inter.getClass().getInterfaces(), tp); interProxy.move(); }
得到的结果为
start
com.sun.proxy.$Proxy0
move...
end
可以看到确实得到了代理类:$Proxy0
也满足了我们的需求,在新生成代理类中加入了我们想加入的功能