【java入门点滴】动态代理模式

简单代理模式,请参考 简单代理模式

 

动态代理模式

  所谓代理,就是需要代理类和被代理类有相同的对外接口或者说成服务,所以代理类一般都必须实现了所有被代理类已实现的接口,因为接口就是制定了一系列对外服务的标准。

正因为动态代理有这样灵活的特性,所以我们在设计动态代理类(DynamicProxy)时不用显式地让它实现与真实主题类(RealSubject)相同的接口(interface),而是把这种实现推迟到运行时。
 
动态代理模式,核心主要是反射;主要使用到了:
  1、java.lang.reflect.InvocationHandler:InvocationHandler接口用来约束调用者实现;
  2、java.lang.reflect.Proxy:Proxy类主要用来获取动态代理对象,主要是重写的invoke方法;
 
动态代理模式
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/**
 * Created by wangzh on 2016/4/21.
 * Description: 动态代理的调用处理类
 */
public class HouseSaleInvocationHandler implements InvocationHandler {

    // 被代理类的实例
    private Object obj = null;

    // 将被代理者的实例传进动态代理类的构造函数中
    public HouseSaleInvocationHandler(Object obj) {
        this.obj = obj;
    }

    /**
     * 生成代理类工厂
     *
     * @param realObj 真实对象
     * @return 返回生成的代理类
     * @author com.tiantian
     */
    public static Object getProxyInstanceFactory(Object realObj) {

        Class<?> classType = realObj.getClass();
        ClassLoader classLoader = classType.getClassLoader();
        Class<?>[] interfaces = classType.getInterfaces();
        InvocationHandler invocationHandler = new HouseSaleInvocationHandler(realObj);
        /*
         * classLoader : 被代理类的类加载器
         * interfaces :被代理类已实现的所有接口,而这些是动态代理类要实现的接口列表
         * invocationHandler :用被代理类的实例创建动态代理类的实例,用于真正调用处理程序
         *
         * return :返回实现了被代理类所实现的所有接口的Object对象,即动态代理,需要强制转型
         */
        //获得代理的实例
        return Proxy.newProxyInstance(classLoader, interfaces, invocationHandler);
    }


    /**
     * 覆盖InvocationHandler接口中的invoke()方法
     * <p>
     * 更重要的是,动态代理模式可以使得我们在不改变原来已有的代码结构
     * 的情况下,对原来的“真实方法”进行扩展、增强其功能,并且可以达到
     * 控制被代理对象的行为,下面的before、after就是我们可以进行特殊
     * 代码切入的扩展点了。
     * </p>
     *
     * @param proxy
     * @param method
     * @param args
     * @return return null
     * @throws Throwable
     */
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {


        System.out.println("dynamic invoke before");
        Object result = null;

        // 除此之外,还可以扩展自有逻辑,比如判定、日志等 
        result = method.invoke(obj, args);

        System.out.println("dynamic invoke after");

        return result;
    }
}

 

客户端:

public class BrokerProxyClient {
    public static void main(String[] args) {

        System.out.println("动态代理测试结果");

        // 房主--即真实对象实例
        HouseSale masterService = new HouseMasterService();


        // 因返回的是Object,需要类型转换
        HouseSale dynamicProxy = (HouseSale) HouseSaleInvocationHandler.getProxyInstanceFactory(masterService);

        // 方式二,利用instanceof检测
        Object obj = HouseSaleInvocationHandler.getProxyInstanceFactory(masterService);
        if (obj instanceof HouseSale) {
            System.out.println("=====dynamicProxy2 instanceof begin=======");
            HouseSale dynamicProxy2 = (HouseSale) obj;
            dynamicProxy2.sale();
            System.out.println("=====dynamicProxy2 instanceof end=======");
        }

        dynamicProxy.sale();

        System.out.println(dynamicProxy.getClass().getName());
    }
}

客户端中,我尝试了两种方式调用;一种是直接强制类型转换;另外一种是利用instanceof进行一次类型检查;目的也是为了更加安全。

输出结果:

动态代理测试结果
=====dynamicProxy2 instanceof begin=======
dynamic invoke before
我是房主,我需要卖房子。
dynamic invoke after
=====dynamicProxy2 instanceof end=======
dynamic invoke before
我是房主,我需要卖房子。
dynamic invoke after
com.sun.proxy.$Proxy0

 

 
参考:
http://haolloyin.blog.51cto.com/1177454/333257/
 
 
posted @ 2016-04-21 15:36  iMhager  阅读(270)  评论(0编辑  收藏  举报