zoukankan      html  css  js  c++  java
  • 设计模式(九)_代理模式

    不知不觉今天已经7月底了,时间过得真快,这个月真热,这篇文章主要来介绍代理模式。

    概述

    代理模式为另一个对象提供一个替身或者占位符以控制对这个对象的访问

    如下图所示

    UML类图

    代理模式类别

    代码实现

    这里是结合springAop,仿造它的实现

    静态代理

    public interface Subject {
    
        void request();
    }
    
    
    // 请求的真实目标对象
    public class RealSubject implements Subject {
        @Override
        public void request() {
            System.out.println("real subject execute request");
        }
    }
    
    
    // 代理对象
    public class Proxy implements Subject {
    
        private RealSubject realSubject;
    
        public Proxy(RealSubject realSubject) {
            this.realSubject = realSubject;
        }
    
        @Override
        public void request() {
            System.out.println("before");
            try {
                realSubject.request();
            } catch (Exception e) {
                System.out.println("ex:" + e);
                throw e;
            } finally {
                System.out.println("after");
            }
    
    
        }
    }
    
    

    客户端调用代码

    public class Client {
    
        public static void main(String[] args) throws Exception {
            Subject subject = new Proxy(new RealSubject());
    
            subject.request();
    
        }
    }
    

    运行结果

    before
    real subject execute request
    after
    

    静态代理有一个很明显的缺点:代理的方法越多,重复代码越多。
    就不符合DRY原则。于是 就产生了动态代理

    动态代理

    jdk代理

    JDK 为我们提供了一种动态代理的实现,通过实现 InvocationHandler 接口来实现动态代理。

    代理类代码

    public class JdkProxySubject implements InvocationHandler {
    
        private RealSubject realSubject;
    
        public JdkProxySubject(RealSubject realSubject) {
            this.realSubject = realSubject;
        }
    
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            System.out.println("before");
            Object result = null;
            try {
                result = method.invoke(realSubject, args);
            } catch (Exception e) {
                System.out.println("ex" + e);
                throw e;
            } finally {
                System.out.println("after");
            }
    
    
            return result;
        }
    }
    
    

    客户端类代码

    public class Client {
    
        public static void main(String[] args) throws Exception {
            Subject subject = (Subject) Proxy.newProxyInstance(Client.class
                    .getClassLoader(), new Class[]{Subject.class}, new JdkProxySubject(new RealSubject()));
    
            subject.request();
    
        }
    }
    
    

    运行结果

    before
    real subject execute request
    after
    

    上面讲了动态代理是解决代码重复的问题。我们来验证下

    首先,在Subject 接口中增加一个hello方法

    public interface Subject {
    
        void request();
    
        void hello();
    }
    
    
    public class RealSubject implements Subject {
        @Override
        public void request() {
            System.out.println("real subject execute request");
        }
    
        @Override
        public void hello() {
            System.out.println("real subject execute hello");
        }
    }
    
    

    静态代理类 如果想要代理hello 这个方法。就要在代理类中实现这个方法

    public class Proxy implements Subject {
    
        private RealSubject realSubject;
    
        public Proxy(RealSubject realSubject) {
            this.realSubject = realSubject;
        }
    
    
        @Override
        public void hello() {
            ...
        }
    }
    
    

    我们看动态代理类,无需改变,直接运行测试类

    public class Client {
    
        public static void main(String[] args) throws Exception {
            Subject subject = (Subject) Proxy.newProxyInstance(Client.class
                    .getClassLoader(), new Class[]{Subject.class}, new JdkProxySubject(new RealSubject()));
    
            subject.hello();
    
        }
    }
    
    

    运行结果

    before
    real subject execute hello
    after
    
    Cglib代理

    代理类

    public class DemoMethodInterceptor implements MethodInterceptor {
        @Override
        public Object intercept(Object object, Method method, Object[] args, MethodProxy proxy) throws Throwable {
            System.out.println("before in cglib");
            Object result = null;
            try {
                result = proxy.invokeSuper(object,args);
            }catch (Exception e){
                System.out.println("get ex :" + e.getMessage());
                throw e;
            }finally {
                System.out.println("after in cglib");
            }
            return result;
        }
    }
    
    

    调用

    public class Client {
    
        public static void main(String[] args) {
            Enhancer enhancer = new Enhancer();
            enhancer.setSuperclass(RealSubject.class);
            enhancer.setCallback(new DemoMethodInterceptor());
            Subject subject = (Subject) enhancer.create();
            subject.request();
        }
    }
    

    运行结果

    before in cglib
    real subject execute request
    after in cglib
    

    JDK代理和Cglib代理区别

    • JDK代理只能针对有接口的类的方法进行代理
    • Cglib基于继承来实现代理,无法对static、final 类进行代理
    • Cglib基于继承来实现代理,无法对private、static 方法 进行代理

    代理模式暂时先分析到这,玩的开心!

  • 相关阅读:
    创建并发布npm包
    ubuntu下python+tornado+supervisor+nginx部署
    Ubuntu下pycharm设定任务栏图标后打开出现问号图标
    Ubuntu下安装keras
    Windows和Ubuntu双系统
    Java获取精确到秒的时间戳
    Jmeter Java请求
    git 生成公钥、私钥方法与clone使用方法
    Oracle 安全管理
    五、python沉淀之路--字典
  • 原文地址:https://www.cnblogs.com/zhenghengbin/p/9384416.html
Copyright © 2011-2022 走看看