• Spring 学习(六)代理模式


    10. 代理模式

    • 案例

    在这里插入图片描述

    10.1 静态代理

    • 角色分析

      • 抽象角色:一般使用接口或者抽象类实现。
      • 真实角色:被代理的角色。
      • 代理角色:代理真实角色,含附属操作。
      • 客户:访问代理对象的角色。
    • 租房案例

      • 定义租赁接口

        /**
         * TODO
         * 租房
         * @author why
         * @since 2021/7/6 9:06
         */
        public interface Rent {
            public void rent();
        }
        
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
        • 7
        • 8
        • 9
      • 定义真实角色

        /**
         * TODO
         * 房东
         * @author why
         * @since 2021/7/6 9:10
         */
        public class Landlord implements Rent {
        
            public void rent() {
                System.out.println("房东要出租房子");
            }
        }
        
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
        • 7
        • 8
        • 9
        • 10
        • 11
        • 12
      • 定义代理角色

        /**
         * TODO
         * 中介
         * @author why
         * @since 2021/7/6 9:14
         */
        public class Proxy implements Rent {
            private Landlord landlord;
            public Proxy() {
            }
            public Proxy(Landlord landlord) {
                this.landlord = landlord;
            }
        
            /**
             * 出租房子
             */
            public void rent() {
                seeHouse();
                landlord.rent();
                signContract();
                fee();
            }
        
            /**
             * 看房
             */
            public void seeHouse(){
                System.out.println("中介带租客看房");
            }
        
            /**
             * 收中介费
             */
            public void fee(){
                System.out.println("收中介费");
            }
        
            /**
             * 签合同
             */
            public void signContract(){
                System.out.println("签租赁合同");
            }
            
        }
        
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
        • 7
        • 8
        • 9
        • 10
        • 11
        • 12
        • 13
        • 14
        • 15
        • 16
        • 17
        • 18
        • 19
        • 20
        • 21
        • 22
        • 23
        • 24
        • 25
        • 26
        • 27
        • 28
        • 29
        • 30
        • 31
        • 32
        • 33
        • 34
        • 35
        • 36
        • 37
        • 38
        • 39
        • 40
        • 41
        • 42
        • 43
        • 44
        • 45
        • 46
      • 客户端访问代理角色

        /**
         * TODO
         * 租客
         * @author why
         * @since 2021/7/6 9:12
         */
        public class Client {
            public static void main(String[] args) {
                // 房东想要出租房子
                Landlord landlord = new Landlord();
                // 中介帮助房东出租房子,包含了附加操作
                Proxy proxy = new Proxy(landlord);
                // 租客找中介租房子
                proxy.rent();
            }
        }
        
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
        • 7
        • 8
        • 9
        • 10
        • 11
        • 12
        • 13
        • 14
        • 15
        • 16
    • 模式优点

      • 可以使真实角色的操作更加纯粹,不必关注一些公共业务。
      • 公共业务交给代理角色,实现了业务的分工。
      • 公共业务发生扩展时,方便集中管理。
    • 模式缺点

      • 一个真实角色就会产生一个代理角色,代码量会翻倍,开发效率会变低。
    • 业务模拟

      • 抽象 AOP 机制

        在这里插入图片描述

      • 定义用户操作接口

        /**
         * TODO
         * 用户服务接口
         * @author why
         * @since 2021/7/6 9:38
         */
        public interface UserService {
            public void add();
            public void delete();
            public void update();
            public void query();
        }
        
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
        • 7
        • 8
        • 9
        • 10
        • 11
        • 12
      • 定义业务操作实现类

        /**
         * TODO
         * 用户接口实现类(真实对象)
         * @author why
         * @since 2021/7/6 9:40
         */
        public class UserServiceImpl implements UserService {
        
            public void add() {
                System.out.println("增加一个用户");
            }
        
            public void delete() {
                System.out.println("删除一个用户");
            }
        
            public void update() {
                System.out.println("修改一个用户");
            }
        
            public void query() {
                System.out.println("查询一个用户");
            }
        }
        
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
        • 7
        • 8
        • 9
        • 10
        • 11
        • 12
        • 13
        • 14
        • 15
        • 16
        • 17
        • 18
        • 19
        • 20
        • 21
        • 22
        • 23
        • 24
      • 定义代理

        /**
         * TODO
         * 代理
         * @author why
         * @since 2021/7/6 9:57
         */
        public class UserServiceProxy implements UserService {
        
            private UserService userService;
        
            public void setUserService(UserService userService) {
                this.userService = userService;
            }
        
            public void add() {
                log("add");
                userService.add();
            }
        
            public void delete() {
                log("delete");
                userService.delete();
            }
        
            public void update() {
                log("update");
                userService.update();
            }
        
            public void query() {
                log("query");
                userService.query();
            }
        
            // 日志方法
            public void log(String msg) {
                System.out.println("[Debug] 使用了"+ msg +"方法");
            }
        }
        
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
        • 7
        • 8
        • 9
        • 10
        • 11
        • 12
        • 13
        • 14
        • 15
        • 16
        • 17
        • 18
        • 19
        • 20
        • 21
        • 22
        • 23
        • 24
        • 25
        • 26
        • 27
        • 28
        • 29
        • 30
        • 31
        • 32
        • 33
        • 34
        • 35
        • 36
        • 37
        • 38
        • 39
      • 定义客户端

        /**
         * TODO
         * 客户端
         * @author why
         * @since 2021/7/6 9:44
         */
        public class Client {
            public static void main(String[] args) {
                UserServiceImpl userService = new UserServiceImpl();
        
                UserServiceProxy userServiceProxy = new UserServiceProxy();
                userServiceProxy.setUserService(userService);
        
                userServiceProxy.add();
            }
        }
        
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
        • 7
        • 8
        • 9
        • 10
        • 11
        • 12
        • 13
        • 14
        • 15
        • 16

    10.2 动态代理

    • 动态代理和静态代理的角色一样

    • 动态代理的代理类是动态生成的,不需要编写。

    • 动态代理分为基于接口的动态代理和基于类的动态代理。

      • 基于接口 — JDK 动态代理
      • 基于类 — CGLIB
      • Java 字节码实现 — Javasist
    • 租房案例

      • 定义租赁接口

        /**
         * TODO
         * 租房
         * @author why
         * @since 2021/7/6 9:06
         */
        public interface Rent {
            public void rent();
        }
        
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
        • 7
        • 8
        • 9
      • 定义真实角色(房东)

        /**
         * TODO
         * 房东
         * @author why
         * @since 2021/7/6 9:10
         */
        public class Landlord implements Rent {
        
            public void rent() {
                System.out.println("房东要出租房子");
            }
        }
        
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
        • 7
        • 8
        • 9
        • 10
        • 11
        • 12
      • 构造代理类生成器

        /**
         * TODO
         * 自动生成代理类
         * @author why
         * @since 2021/7/6 13:43
         */
        public class ProxyInvocationHandler implements InvocationHandler {
        
            // 被代理的接口
            private Rent rent;
        
            public void setRent(Rent rent) {
                this.rent = rent;
            }
        
            // 获得代理类
            public Object getProxy(){
                return Proxy.newProxyInstance(this.getClass().getClassLoader(), rent.getClass().getInterfaces(), this);
            }
        
            // 处理代理实例并返回结果
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        
                // 动态代理由反射机制实现
                Object result = method.invoke(rent, args);
                return result;
            }
        }
        
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
        • 7
        • 8
        • 9
        • 10
        • 11
        • 12
        • 13
        • 14
        • 15
        • 16
        • 17
        • 18
        • 19
        • 20
        • 21
        • 22
        • 23
        • 24
        • 25
        • 26
        • 27
        • 28
      • 定义客户端

        /**
         * TODO
         * 客户端
         * @author why
         * @since 2021/7/6 13:54
         */
        public class Client {
            public static void main(String[] args) {
        
                // 真实角色
                Landlord landlord = new Landlord();
        
                // 代理角色(由 InvocationHandler 获取)
                ProxyInvocationHandler pih = new ProxyInvocationHandler();
        
                // 通过调用处理程序处理要调用的接口对象
                pih.setRent(landlord);
                Rent proxy = (Rent) pih.getProxy();
                proxy.rent();
            }
        }
        
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
        • 7
        • 8
        • 9
        • 10
        • 11
        • 12
        • 13
        • 14
        • 15
        • 16
        • 17
        • 18
        • 19
        • 20
        • 21
    • 模式优点

      • 可以使真实角色的操作更加纯粹,不必关注一些公共业务。
      • 公共业务交给代理角色,实现了业务的分工。
      • 公共业务发生扩展时,方便集中管理。
      • 一个动态代理类代理的是一个接口,一般就是一类业务。
      • 一个动态代理可以代理多个类,前提是这些类实现了同一个接口。
    • 业务模拟

      • 定义用户操作接口

        /**
         * TODO
         * 用户服务接口
         * @author why
         * @since 2021/7/6 9:38
         */
        public interface UserService {
            public void add();
            public void delete();
            public void update();
            public void query();
        }
        
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
        • 7
        • 8
        • 9
        • 10
        • 11
        • 12
      • 定义业务操作实现类

        /**
         * TODO
         * 用户接口实现类(真实对象)
         * @author why
         * @since 2021/7/6 9:40
         */
        public class UserServiceImpl implements UserService {
        
            public void add() {
                System.out.println("增加一个用户");
            }
        
            public void delete() {
                System.out.println("删除一个用户");
            }
        
            public void update() {
                System.out.println("修改一个用户");
            }
        
            public void query() {
                System.out.println("查询一个用户");
            }
        }
        
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
        • 7
        • 8
        • 9
        • 10
        • 11
        • 12
        • 13
        • 14
        • 15
        • 16
        • 17
        • 18
        • 19
        • 20
        • 21
        • 22
        • 23
        • 24
      • 定义代理生成器

        /**
         * TODO
         * 自动生成代理类
         * @author why
         * @since 2021/7/6 13:43
         */
        public class ProxyInvocationHandler implements InvocationHandler {
        
            // 被代理的接口
            private Object target;
        
            public void setTarget(Object target) {
                this.target = target;
            }
        
            // 获得代理类
            public Object getProxy(){
                return Proxy.newProxyInstance(this.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
            }
        
            // 处理代理实例并返回结果
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        
                log(method.getName());
                // 动态代理由反射机制实现
                return method.invoke(target, args);
            }
        
            public void log(String msg){
                System.out.println("执行了" + msg + "方法");
            }
        }
        
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
        • 7
        • 8
        • 9
        • 10
        • 11
        • 12
        • 13
        • 14
        • 15
        • 16
        • 17
        • 18
        • 19
        • 20
        • 21
        • 22
        • 23
        • 24
        • 25
        • 26
        • 27
        • 28
        • 29
        • 30
        • 31
        • 32
      • 定义客户端

        /**
         * TODO
         * 客户端
         * @author why
         * @since 2021/7/6 15:00
         */
        public class Client {
            public static void main(String[] args) {
                UserServiceImpl userService = new UserServiceImpl();
                ProxyInvocationHandler pih = new ProxyInvocationHandler();
                pih.setTarget(userService);
                UserService proxy = (UserService) pih.getProxy();
                proxy.add();
            }
        }
        
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
        • 7
        • 8
        • 9
        • 10
        • 11
        • 12
        • 13
        • 14
        • 15

  • 相关阅读:
    Android学习笔记 43. RX思维的魅力
    Python优雅遍历字典删除元素的方法
    Java实现在线SQL编程【完整版】
    MyBatis总结(2)- MyBatis实现原理(三)
    [Tools: git] Github Pull Request
    神经网络控制系统设计,神经网络技术及其应用
    这是一篇用python画3D爱心的代码
    Python+Pytest+Allure+Git+Jenkins数据驱动接口自动化测试框架
    jmeter单接口和多接口测试
    ORA-12541:TNS:no listener 无监听程序
  • 原文地址:https://blog.csdn.net/qq_42651415/article/details/133239211