从JDK1.3开始,java中引入了动态代理机制,有关的接口和类是InvocationHandler和Proxy,都位于java.lang.reflect包下。
InvocationHandler接口只定义了一个抽象方法:
Object invoke(Object proxy, Method method, Object[] args)
Proxy类中主要的2个静态方法:
Class<?> getProxyClass(ClassLoader loader, Class<?>... interfaces)
Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)
getProxyClass返回一个动态创建的代理类(Class),newProxyInstance则返回改代理类的实例(Object)。
借助于JVM的支持,可以在运行时动态生成代理类(“代理角色”),我们就可以解决静态代理模式中代码膨胀的问题。
使用了动态代理后,“代理角色”将不用手动生成,而由JVM在运行时,通过指定类加载器、接口数组、调用处理程序这3个参数来动态生成。
下面是一个动物世界的动态代理 example:
动物接口, 有一个奔跑的抽象方法
/** * Created by jiangzhq on 2015/6/30. */ public interface Animal { void run(); }动物接口的实现类——老虎
public class Tiger implements Animal { public void run() { System.out.println("森林之王——老虎在跑"); } }
动物接口的实现类——狮子
public class Lion implements Animal{ public void run() { System.out.println("草原之王——狮子在跑"); } }
动态角色:动态生成代理类
public class DynamicProxy implements InvocationHandler { // 被代理的目标对象 private Object target; // 通过构造函数注入 DynamicProxy(Object obj) { this.target = obj; } // 通过反射动态生成对象 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { doBefore(); Object result = method.invoke(target, args); doAfter(); return result; } public void doBefore(){ System.out.println("动态生成代理类之前"); } public void doAfter(){ System.out.println("动态生成代理类之后"); } // 工厂方法,获取代理类实例 static <T> T factory(Object obj) { Class cls = obj.getClass(); return (T)Proxy.newProxyInstance(cls.getClassLoader(), cls.getInterfaces(), new DynamicProxy(obj)); } }
客气端测试类
public class DynamicProxyTest { public static void main(String[] args) { Animal tiger = new Tiger(); Animal tigerProxy = (Animal) DynamicProxy.factory(tiger); tigerProxy.run(); Animal lion = new Lion(); Animal lionProxy = (Animal) DynamicProxy.factory(lion); lionProxy.run(); } }
动态代理更好地面向了抽象,减少了重复的code,有更好的可维护性,符合面向接口编程的原则。
缺点:JDK的动态代理只能代理接口,不能代理没有接口的类。