从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的动态代理只能代理接口,不能代理没有接口的类。