• 大话设计模式之代理模式


    代理模式

      可以理解为一个类代表另一个类的功能。这种类型的设计模式属于结构型模式。

    通过代码分析理解 

    //买房动作
    public interface BuyHouse {
        void buyHouse();
    }
    
    //客户直接买房
    public class BuyHouseImpl implements BuyHouse {
        @Override
        public void buyHouse() {
            System.out.println("我要买房子");
        }
    }
    
    //通过代理(中介)买房
    public class BuyHouseProxy implements BuyHouse {
        BuyHouse buyHouse;
    
        public BuyHouseProxy(BuyHouse buyHouse){
            this.buyHouse=buyHouse;
        }
    
        @Override
        public void buyHouse() {
            System.out.println("买房前准备");
            buyHouse.buyHouse();
            System.out.println("买房后装修");
        }
    }

    main测试

    public class MianTest {
    
        public static void main(String[] args){
            BuyHouse buyHouse = new BuyHouseImpl();
            BuyHouseProxy buyHouseProxy = new BuyHouseProxy(buyHouse);
            buyHouseProxy.buyHouse();
        }
    
    }
    
    //执行结果
    买房前准备
    我要买房子
    买房后装修

    代理模式的应用场景:

    1、远程代理,也就是为一个对象在不同的地址空间提供局部代表。

    2、虚拟代理,是根据需要创建开销很大的对象。通过他来存放实例化需要很长时间的真是对象。

    3、安全代理,用来控制真实对象访问时的权限。

    4、智能引用,是指当调用真实对象时,代理处理另外一些事。

    2018/9/10修改

    上述代理模式是基于静态代理的一种实现,那么下面来讲解基于jdk的动态代理

    动态代理实现之jdk动态代理

    在java的动态代理机制中,有两个重要的类或接口,一个是 InvocationHandler(Interface)、另一个则是 Proxy(Class),这一个类和接口是实现我们动态代理所必须用到的。

    实现原理:采用反射技术

    每一个动态代理类都必须要实现InvocationHandler这个接口,并且每个代理类的实例都关联到了一个handler,当我们通过代理对象调用一个方法的时候,这个方法的调用就会被转发为由InvocationHandler这个接口的 invoke 方法来进行调用。

    代码实现(还是基于买房示例,现在我们只需创建一个动态代理类即可)

    package com.chenpt.designModel.proxyFactory;
    
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    
    /**
     * @Author: chen
     * @Description: jdk的动态代理
     * @Date: created in 2018/9/10
     * @Modified By:
     */
    public class MyProxy implements InvocationHandler {
    
        public Object target;
    
        MyProxy(Object target){
            this.target = target;
        }
    
        /**
         * @param proxy  需要代理的真实类
         * @param method 真实类的方法
         * @param args   方法所需参数
         * @return
         * @throws Throwable
         */
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            System.out.println("++++++before " + method.getName() + "++++++");
            Object result = method.invoke(target,args);
            System.out.println("++++++after " + method.getName() + "++++++");
            return result;
        }
    }
    

      客户端

    package com.chenpt.designModel.proxyFactory;
    import java.lang.reflect.Proxy;
    
    /**
     * @Author: chenpengtao
     * @Description:
     * @Date: created in 2018/7/24
     * @Modified By:
     */
    public class MianTest {
    
    
        public static void main(String[] args){
            BuyHouse buyHouse2 = new BuyHouseImpl2();
    
            MyProxy myProxy = new MyProxy(buyHouse2);
            try {
                BuyHouse subject = (BuyHouse) Proxy.newProxyInstance(myProxy.getClass().getClassLoader(),buyHouse2.getClass().getInterfaces(),myProxy);
                subject.buyHouse();
            } catch (Throwable throwable) {
                throwable.printStackTrace();
            }
    
        }
    
    }
    //执行结果
    ++++++before buyHouse++++++
    我要买房子2
    ++++++after buyHouse++++++
    

     

    动态代理实现之cglib代理

      cglib是针对类来实现代理的,原理是对指定的业务类生成一个子类,并覆盖其中业务方法实现代理。不能对final修饰的类进行代理。 

    实现原理:采用字节码(asm)技术

    还以买房为例,现在只需实现cglib代理类即可

    package com.chenpt.designModel.proxyFactory;
    
    import org.springframework.cglib.proxy.Enhancer;
    import org.springframework.cglib.proxy.MethodInterceptor;
    import org.springframework.cglib.proxy.MethodProxy;
    import org.springframework.context.annotation.Primary;
    
    import java.lang.reflect.Method;
    
    /**
     * @Author: chen
     * @Description: 基于cglib的动态代理
     * @Date: created in 2018/9/10
     * @Modified By:
     */
    public class MyCglib implements MethodInterceptor{
    
        private Object target;
    
        //相当于JDK动态代理中的绑定
        public Object getInstance(Object target) {
            this.target = target;  //给业务对象赋值
            Enhancer enhancer = new Enhancer(); //创建加强器,用来创建动态代理类
            enhancer.setSuperclass(this.target.getClass());  //为加强器指定要代理的业务类(即:为下面生成的代理类指定父类)
            //设置回调:对于代理类上所有方法的调用,都会调用CallBack,而Callback则需要实现intercept()方法进行拦
            enhancer.setCallback(this);
            // 创建动态代理类对象并返回
            return enhancer.create();
        }
    
        @Override
        public Object intercept(Object obj, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
            System.out.println("预处理——————");
            methodProxy.invokeSuper(obj, args); //调用业务类(父类中)的方法
            System.out.println("调用后操作——————");
            return null;
        }
    }
    

      客户端

    package com.chenpt.designModel.proxyFactory;
    import java.lang.reflect.Proxy;
    
    /**
     * @Author: chenpengtao
     * @Description:
     * @Date: created in 2018/7/24
     * @Modified By:
     */
    public class MianTest {
    
    
        public static void main(String[] args){
            BuyHouse buyHouse2 = new BuyHouseImpl2();
    
            MyCglib myCglib = new MyCglib();
    
            buyHouse2 = (BuyHouse) myCglib.getInstance(buyHouse2);
            buyHouse2.buyHouse();
        }
    
    }
    //执行结果
    预处理——————
    我要买房子2
    调用后操作——————
    

      

  • 相关阅读:
    Linux/Unix 新手和专家教程
    恢复Ext3下被删除的文件
    如何调试bash脚本
    8个实用而有趣Bash命令提示行
    使用grep恢复被删文件内容
    一些非常有意思的杂项资源
    chmod -x chmod的N种解法
    纯文本配置还是注册表
    面向对象的Shell脚本
    你可能不知道的Shell
  • 原文地址:https://www.cnblogs.com/chenpt/p/9365144.html
Copyright © 2020-2023  润新知