代理模式之动态代理

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

 

猜你喜欢

转载自geeksun.iteye.com/blog/2223143
今日推荐