反射与代理设计模式
如果要想动态的创建代理对象,那么就需要使用一个java.lang.reflect.Proxy程序类,在这个类中提供有一个动态实例化新的代理对象的操作方法:
public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) throws IllegalArgumentException
在本方法之中参数的作用如下:
· ClassLoader loader:类加载器,确定代理对象的产生使用的类加载器是什么;
· Class<?>[] interfaces:要代理类所实现的接口;
· InvocationHandler h:实现了代理调用的处理;
如果要想实现整个动态代理操作,那么核心的关键除了Proxy类之外,还有一个InvocationHandler接口,那么这个接口定义如下:
public interface InvocationHandler{ /* * 动态代理设计模式之中的代理处理方法 * @param proxy 代理对象 * @param method 真实主题要调用的方法,结合本类的真实对象可以反射调用方法(真实主题) * @param args 表示执行方法时所需要的参数 * @return Method 对象反射调用真实主题方法 * @throws Throwable */ public Object invoke(Object proxy,Method method,Object[] args) throws Throwable; }
实现动态代理:
1 package cn.test; 2 3 import java.lang.reflect.InvocationHandler; 4 import java.lang.reflect.Method; 5 import java.lang.reflect.Proxy; 6 7 interface ISubject{ 8 public void get(); 9 } 10 class RealISubject implements ISubject{ 11 public void get(){ 12 System.out.println("吃饭"); 13 } 14 } 15 16 class ProxyImpl implements InvocationHandler{ 17 private Object real; 18 /** 19 * 如果要想通过动态代理实现类操作invoke()方法,那么必须创建动态对象,同时要保存被代理对象 20 * 如果要想动态创建代理对象,那么必须首先要知道真实对象 21 * @param obj 要代理的真实对象 22 * @return proxy 动态创建的代理对象 23 * 24 */ 25 public Object bin(Object obj){ 26 this.real = obj;//保存真实对象 27 return Proxy.newProxyInstance(obj.getClass().getClassLoader(),obj.getClass().getInterfaces(),this); 28 } 29 public void prepare(){ 30 System.out.println("餐厅人员准备食物"); 31 } 32 public void after(){ 33 System.out.println("餐厅人员清理餐桌"); 34 } 35 public Object invoke(Object proxy,Method method, Object[] args) throws Throwable{ 36 this.prepare(); 37 Object ret = method.invoke(this.real, args); //调用真实方法 38 this.after(); 39 return ret; 40 } 41 } 42 public class TestLocal{ 43 public static void main(String[] args) { 44 ISubject subject = (ISubject) new ProxyImpl().bin(new RealISubject()); 45 subject.get(); 46 } 47 }
结果:
餐厅人员准备食物
chifan
餐厅人员清理餐桌
总结:此时的Proxy的代理类不会再局限于某一个特定的接口对象操作,而是可以直接进行所有接口子类对象的代理操作,这就是动态代理设计模式的雏形。