动态代理的使用方式
一、简介
首先介绍下什么是代理,所谓代理就是当原有的类的方法不足以满足我们的需求的时候,我们需要额外进行一些其他的操作的时候,为了尽量不改写业务逻辑,我们不直接调用类本身,而是借助另一个包装好了所有需求的方法的类来实现,当然,这个类里也可以调用原有类的方法,如果需要调用原有类的方法的话(大多数情况下)就需要让该类持有原类的一个对象作为他的成员变量,以方便对原有类中方法的调用。那么这个类就可以称之为代理类了,代理的工作流程如下:
代理本身又分为静态代理和动态代理,这里的静态和动态分别指的是什么呢,我们知道,要让代理类执行原有类里的方法,我们得让代理类持有原有类的对象,这就意味着,如果有多个类需要代理,我们就得写多个代理类,这个是静态代理,如果是动态代理的话,只需要一个代理类就可以搞定,因为动态代理类不需要持有原类的对象,他需要代理类实现InvocationHandler接口,这个接口有一个需要实现的方法:public object invoke(Object proxy, Method method, Object[] args);这个方法里面我们要写的就是动态调用的业务逻辑了,可以调用method.invoke(proxy,args)来调用proxy对象对应的method方法,传入args参数,并返回object返回值,那问题来了,这个invoke函数是谁调用的呢,这个invoke函数其实是由代理对象调用接口里的方法动态调用的,换句话说,代理对象定义为接口类型的,当他调用接口里的方法的时候,并不是调用实现类里的方法,而是转头调用了这个invoke的方法,那问题又来了,如何获取代理对象呢,可以通过Proxy.newProxyInstance方法获取,将其返回类型强转成对应的接口类型,就可以调用接口里的方法了。返回类型不能转成实现类的类型,不然会报错,报一个类转换错误。
二、涉及到的类
InvocationHandler 说明:这是一个接口,代理类实现这个接口,然后实现接口中的invoke方法,作为回调使用的方法。
Proxy 说明:用来获得一个代理对象
三、设计的结构
从上往下说吧:
- 首先所有准备被代理的类要各自有一个接口
- 可以有多个准备被代理的类,里面封装好业务逻辑方法
- 要有一个实现了InvocationHandler的代理类,如果需要调用原有类的方法,在代理类中可以封装一个Object类型的成员变量,必须要实现好invoke方法,封装好需要代理的逻辑,可以通过调用method.invoke(object,args)的方法调用对应object对象的method方法,并传入args参数,其中object对象就是我们上面说的成员变量。
- 通过Proxy.newProxyInstance方法获取一个代理对象,需要传入三个参数:被代理类的类加载器,被代理类的接口列表,代理类对象实例。
- 代理对象强转成对应的接口类型,并调用接口里的方法,可以接收返回值。
注:代理对象和代理类对象实例不是一个事情哈,代理对象是通过Proxy.newProxyInstance获取到的,可以强转成接口类型的,代理类对象是指我们定义的实现InvocationHandler的类的对象实例。
四、调用方式
这里可能有点冗余,这里是从下往上说的:
- 通过Proxy.newProxyInstance方法获取一个代理对象,需要传入三个参数:被代理类的类加载器,被代理类的接口列表,代理类对象实例。
- 将这个代理对象强转成对应的接口类型,并调用接口里的方法,可以接收返回值。
- 上一步操作将会自动跳用代理类里的invoke方法
- invoke方法里可以通过执行:method.invoke(object,args)调用object对象的method方法,并传入args参数,可以接收返回值。这个object需要提前写成Object类型的成员变量,在第一步需要代理类对象实例,可以在获取实例的时候就把对应的类(被代理的类)生成的对象传进去。
- 上一步中调用method方法会自动调用object对象里的method方法。
- object对象对应的类(被代理的类)需要继承接口,因为第一步的时候就要拿到对应被代理类的接口列表。
五、范例代码
接口:
1 package goods; 2 3 public interface Healthy_drink { 4 void sell(); 5 int getMoney(); 6 }
被代理的类:
1 package goods; 2 3 public class Water implements Healthy_drink{ 4 private int money; 5 6 public Water(){ 7 8 } 9 10 public Water(int money){ 11 this.money = money; 12 } 13 14 @Override 15 public int getMoney(){ 16 return this.money; 17 } 18 19 @Override 20 public void sell() { 21 System.out.println("water has selled by " + this.money); 22 } 23 }
代理类:
1 package proxy; 2 3 import java.lang.reflect.InvocationHandler; 4 import java.lang.reflect.Method; 5 6 public class Dynamic_proxy implements InvocationHandler { 7 private Object object; 8 9 public Dynamic_proxy(){ 10 11 } 12 13 public Dynamic_proxy(Object object){ 14 this.object = object; 15 } 16 17 @Override 18 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { 19 System.out.println("through dynamic proxy"); 20 System.out.println(proxy.getClass().getName()); 21 Object result = method.invoke(object, args); 22 return result; 23 } 24 }
调用:
1 Water water = new Water(10); 2 Dynamic_proxy dynamic_proxy; 3 int money; 4 dynamic_proxy = new Dynamic_proxy(water); 5 Healthy_drink water_proxy = (Healthy_drink) Proxy.newProxyInstance(Water.class.getClassLoader(), Water.class.getInterfaces(), dynamic_proxy); 6 money = water_proxy.getMoney(); 7 System.out.println("water value is " + money); 8 water_proxy.sell();