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

    简介

    定义

    代理模式定义:给某一个对象提供一个代理,通过代理来控制对该对象的引用。

    相关角色

    Subject: 抽象主题角色接口。是RealSubject和Proxy的共用接口。

    RealSubject: 真实主题角色,实现了Subject接口。

    Proxy: 代理角色,内部有RealSubject的引用,因此可操作RealSubject。同时代理对象提供了真实对象拥有的接口,因此在任何时刻都能替代RealSubject。并且通过代理对象执行RealSubject的操作前后进行处理。

    代理类型:

    1.静态代理

    静态代理由程序员创建或由特定工具自动生成代理类的源代码,再对其编译。在程序运行前,代理类的.class文件就已经存在了。

    实现静态代理的两种方法:

    聚合式静态代理

    聚合式静态代理模式UML类图

     实现代码:

    /**
     * Subject 
     * 抽象主题接口
     * @author
     * @create 2018-03-29 14:16
     **/
    public interface Subject {
    
        void doSomething();
    }
    /**
     * RealSubject
     * 真实主题类
     * @author
     * @create 2018-03-29 14:21
     **/
    public class RealSubject implements Subject {
        @Override
        public void doSomething() {
            System.out.println("RealSubject do something");
        }
    }
    /**
     * Proxy
     * 代理类
     * @author
     * @create 2018-03-29 14:22
     **/
    public class Proxy implements Subject {
    
        // 以聚合方式实现代理
        private RealSubject realSubject;
    
        public Proxy(RealSubject realSubject) {
            this.realSubject = realSubject;
        }
    
        @Override
        public void doSomething() {
            System.out.println("Do something before");
            realSubject.doSomething();
            System.out.println("Do something after");
        }
    }
    /**
     * Client
     * client测试代码
     * @author
     * @create 2018-03-29 14:26
     **/
    public class Client {
        public static void main(String[] args) {
            // 聚合式静态代理测试
            RealSubject realSubject = new RealSubject();
            Proxy proxy = new Proxy(realSubject);
            proxy.doSomething();
    
    
        }
    }
    继承式静态代理

    继承式静态代理模式UML类图

     

    实现代码:

    抽象主题接口类Subject和真实主题类RealSubject与聚合方式中的相同,不再复制。

    /**
     * Proxy2
     * 代理类
     * @author
     * @create 2018-03-29 15:02
     **/
    public class Proxy2 extends RealSubject {
    
        @Override
        public void doSomething() {
            System.out.println("Do something before");
            super.doSomething();
            System.out.println("Do something after");
        }
    }
    /**
     * Client
     * client测试代码
     * @author
     * @create 2018-03-29 14:26
     **/
    public class Client {
        public static void main(String[] args) {
            
            // 继承式静态代理测试
            Proxy2 proxy2 = new Proxy2();
            proxy2.doSomething();
    
        }
    }

     聚合方式先比继承方式更加灵活。

     静态代理一般是一个真实主题类对应一个代理类,当抽象主题接口存在多个主题实现类时,对应的代理类也会逐渐增多。这时候如果想要一个代理类能代理多个实现类的话,

    则需要使用动态代理进行处理。

    2.动态代理

    动态代理指的是代理类由程序在运行时动态生成,不用手动编写。

    动态代理实现的几种方式:jdk动态代理、cglib动态代理

    jdk动态代理

    实现代码:

    抽象主题接口类Subject和真实主题类RealSubject与聚合方式中的相同,不再复制。

    /**
     * JDKDynamicProxy
     * jdkd动态代理
     *
     * @author
     * @create 2018-03-29 16:17
     **/
    public class JDKDynamicProxy implements InvocationHandler {
    
        private Object target;
    
        public JDKDynamicProxy(Object target) {
            this.target = target;
        }
    
        public <T> T getProxy() {
            return (T) Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
        }
    
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            System.out.println("Do something before");
            Object result = method.invoke(target, args);
            System.out.println("Do something after");
            return result;
        }
    }
    /**
     * Client
     * client测试代码
     * @author
     * @create 2018-03-29 14:26
     **/
    public class Client {
        public static void main(String[] args) {
            
            // jdk动态代理测试
            Subject subject = new JDKDynamicProxy(new RealSubject()).getProxy();
            subject.doSomething();
    
        }
    }

    jdk动态代理支持一个代理类可以代理多个主题实现类的问题,但是还有一个问题就是只能动态代理接口,而不能代理不是接口的类。

    cglib动态代理

    实现代码:

     抽象主题接口类Subject和真实主题类RealSubject与聚合方式中的相同,不再复制。

    此处选用spring框架中的cglib实现。

    /**
     * Fish
     * 真实主题类
     * @author
     * @create 2018-03-29 17:00
     **/
    public class Fish {
    
        public void swim() {
            System.out.println("Do you like swimming");
        }
    }
    /**
     * CGLibDynamicProxy
     * cglib动态代理
     * @author
     * @create 2018-03-29 16:37
     **/
    public class CGLibDynamicProxy implements MethodInterceptor {
    
        private static CGLibDynamicProxy instance = new CGLibDynamicProxy();
    
        public static CGLibDynamicProxy getInstance() {
            return instance;
        }
    
        public <T> T getProxy(Class<T> cls) {
            return (T) Enhancer.create(cls, this);
        }
    
        @Override
        public Object intercept(Object target, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
            System.out.println("Do something before");
            Object result = methodProxy.invokeSuper(target, args);
            System.out.println("Do something after");
            return result;
        }
    }
    /**
     * Client
     * client测试代码
     * @author
     * @create 2018-03-29 14:26
     **/
    public class Client {
        public static void main(String[] args) {
    
            // cglib动态代理测试
            Fish fish = CGLibDynamicProxy.getInstance().getProxy(Fish.class);
            fish.swim();
        }
    }

     cglib可以代理没有接口的类。

    参考资料:https://juejin.im/entry/595f53835188250d920875e3

  • 相关阅读:
    Executors源码之线程池
    Java序列化对字段名的影响
    Spring Cloud Alibaba(二)
    Security版本冲突,老版本共用服务接入新版本服务
    记一次虚拟机崩溃事件和解决方法(CentOS7)
    vue-cli 项目构建学习笔记(Vue3)
    IDEA插件-IDE Eval Reset
    Docker的学习
    Spring Security的学习
    Spring MVC框架的设计理念
  • 原文地址:https://www.cnblogs.com/zuidongfeng/p/8670200.html
Copyright © 2011-2022 走看看