zoukankan      html  css  js  c++  java
  • 设计模式之代理模式

    代理模式

    • 作用:在不改变原有代码的基础上,增加或扩展额外的功能
    • 静态代理
    //1,被代理类需要实现的接口,代理类也要实现该接口,该接口对用户使用
    interface FlightMachine{
        void fly();
    }
    //2,被代理类实现接口
    class FlightMachineImpl implements FlightMachine{
    
        @Override
        public void fly() {
            System.out.println("我可以飞");
        }
    }
    //3,代理类实现接口
    class FlightProxy implements FlightMachine{
        //4,代理类引用被代理对象
        private FlightMachine flightMachine;
    
        //5,写有参构造方法得到被代理对象实例
        public FlightProxy(FlightMachine flightMachine){
            super();
            this.flightMachine=flightMachine;
        }
    
        @Override
        public void fly() {
            //增加额外的功能
            System.out.println("我可以发射导弹");
            flightMachine.fly();
            //增加额外的功能
            System.out.println("我可以航拍");
        }
    }
    public class TestProxy {
        public static void main(String[] args) {
            FlightMachine flightMachine = new FlightMachineImpl();
            FlightMachine flightProxy = new FlightProxy(flightMachine);
            flightProxy.fly();
        }
    }
    
    console:
    我可以发射导弹
    我可以飞
    我可以航拍
    

    小结:代理类和被代理类都需要实现同一个接口,且代理类预先设定,造成服务单一,要是其他类需要代理则需要更多代理类,不易扩展,缺点比较明显,适用场景不广。

    • 动态代理
      • JDK代理
        • 使用JDK自带的代理类,制造代理工厂
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    import java.lang.reflect.Proxy;
    
    //1,被代理类实现的接口
    interface FlightMachine{
        void fly();
    }
    //2,被代理类需要至少实现的一个接口
    class FlightMachineImpl implements FlightMachine{
        @Override
        public void fly() {
            System.out.println("我可以飞");
        }
    }
    //3,创建动态代理的工厂类,用来动态生成代理类对象
    class FlightProxyFactory{
        //4,需要引用被代理的对象
        private Object target;
    
        //5,写有参构造方法得到代理目标实例
        public FlightProxyFactory(Object target) {
            this.target = target;
        }
    
        //6,提供一个获取代理类对象的方法
        public Object getProxyInstance(){
            //用JDK自带的reflect包的Proxy创建代理类实例
            /*
            @Proxy.newProxyInstance(Param1,Param2,Param3){ }
            参数1:类加载器,一般一个项目只有一个类加载器,所以选取比较方便获取的类来getClassLoader()就行
            参数2:代理目标所实现的所有接口,通过.getClass().getInterfaces()获得
            参数3:方法调用处理器
             */
            return Proxy.newProxyInstance(target.getClass().getClassLoader(),
                    target.getClass().getInterfaces(), new InvocationHandler() {
                        /*
                        invoke(Param1,Param2,Param3){  }
                        参数1:代理类对象
                        参数2:被代理类(代理目标)需要执行的方法
                        参数3:执行方法需要的参数
                         */
                        @Override
                        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                            //增加额外的功能
                            System.out.println("我可以发射导弹");
                            //通过反射来调用代理目标方法
                            Object procedure = method.invoke(target, args);
                            //增加额外的功能
                            System.out.println("我可以航拍");
                            return procedure;
                        }
                    });
        }
    
    }
    
    public class TestProxy {
        public static void main(String[] args) {
            FlightMachine flightMachine = new FlightMachineImpl();
            FlightProxyFactory flightProxyFactory = new FlightProxyFactory(flightMachine);
            Object proxyInstance = flightProxyFactory.getProxyInstance();
            if (proxyInstance instanceof FlightMachine){
                FlightMachine machineProxy = (FlightMachine) proxyInstance;
                machineProxy.fly();
            }
        }
    }
    console:
    我可以发射导弹
    我可以飞
    我可以航拍
    

    小结:建立代理工厂,根据需要的类动态生成代理类,虽然代理目标不固定,但是需要实现至少一个接口,不是所有的类都实现了接口或者继承了某个类,所以还不够好,但是JDK代理在反射生成代理类方面是作用较好,和其他动态代理方式配合使用效果更好。

    • CGLIB代理
      • 使用第三方代理包,cglib和asm两个包需要引入,核心接口是MethodInterceptor,核心类是Enhancer,给被代理类动态生成一个子类来进行代理(子类对父类来说就相当于扩展了功能)
    import net.sf.cglib.proxy.Enhancer;
    import net.sf.cglib.proxy.MethodInterceptor;
    import net.sf.cglib.proxy.MethodProxy;
    
    import java.lang.reflect.Method;
    
    
    //1,被代理类
    class FlightMachineImpl {
        public void fly() {
            System.out.println("我可以飞");
        }
    }
    //2,创建cglib动态代理的工厂类,用来动态生成代理类、代理类对象,并实现MethodInterceptor接口
    class CglibProxyInterceptor implements MethodInterceptor {
        //3,引用代理目标的对象
        private Object target;
    
        //4,写有参构造方法得到代理目标实例
        public CglibProxyInterceptor(Object target) {
            this.target = target;
        }
    
        //5,提供一个获取代理类对象的方法
        public Object getProxyInstance(){
            //6,用cglib包的Enhancer创建代理类,且该代理类需要继承代理目标成为其子类
            Enhancer enhancer = new Enhancer();
            //7,将代理目标设置为代理类的父类
            enhancer.setSuperclass(target.getClass());
            //8,设置回调函数
            enhancer.setCallback(this);
            //9,创建代理类对象
            return enhancer.create();
        }
        //6,实现intercept方法
        /*
            @intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy){ }
            参数1 o:被代理的对象
            参数2 method:代理对象的方法,这里是FlightMachineImpl的fly()方法
            参数3 objects:方法的参数
            参数4 methodProxy:方法代理,这里代理的是cglib代理的fly()方法
             */
        @Override
        public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
            System.out.println("我可以发射导弹");
            Object result = method.invoke(target, objects);
            System.out.println("我可以航拍");
            //methodProxy的invokeSuper可以实现相同的效果
    //        Object result = methodProxy.invokeSuper(o, objects);
            return result;
        }
    }
    
    public class TestProxy {
        public static void main(String[] args) {
            CglibProxyInterceptor cglibProxyInterceptor = new CglibProxyInterceptor(new FlightMachineImpl());
            Object proxyInstance = cglibProxyInterceptor.getProxyInstance();
            if (proxyInstance instanceof FlightMachineImpl){
                FlightMachineImpl flightMachine = (FlightMachineImpl) proxyInstance;
                flightMachine.fly();
            }
        }
    }
    console:
    我可以发射导弹
    我可以飞
    我可以航拍
    

    小结:使用cglib代理,代理目标不用实现接口或继承类,只需根据该被代理类生成子类作为其代理类完成代理,和JDK代理一起在spring aop中使用广泛。


    至此,若有纰漏,望各位不吝赐教

  • 相关阅读:
    .NET Core 3.0之创建基于Consul的Configuration扩展组件
    .NET Core 3.0之深入源码理解Configuration(三)
    .NET Core 3.0之深入源码理解Configuration(二)
    .NET Core 3.0之深入源码理解Configuration(一)
    python __getattr__ & __getattribute__ 学习
    nginx+uwsgi+flask+supervisor 项目部署
    Read a large file with python
    MySQL 基础回顾(2020/06/14修改)
    Linux运维: Rsync同步数据(ubuntu16.04+windows10)
    斐波那契数列的5种python实现写法
  • 原文地址:https://www.cnblogs.com/0nePlece/p/13263171.html
Copyright © 2011-2022 走看看