zoukankan      html  css  js  c++  java
  • 【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/
     
     
    点滴积累,每天进步一点点!O(∩_∩)O~
  • 相关阅读:
    python的paramiko模块简单应用
    python单线程下实现多个socket并发
    python之协程
    python之生产者消费者模型
    python进程之间修改数据[Manager]与进程池[Pool]
    python的进程间的数据交互
    vmware搭建vSAN提示磁盘不合格或者看不到磁盘的解决办法
    python之多并发socket
    OOP的几个不常用的方法
    HTTP 头和 PHP header() 函数
  • 原文地址:https://www.cnblogs.com/hager/p/5417188.html
Copyright © 2011-2022 走看看