• 3.2 AOP之代理模式


    AOP

    3.2、代理模式

    3.2.1、概念

    ①介绍

    二十三种设计模式中的一种,属于结构型模式。它的作用就是通过提供一个代理类,让我们在调用目标方法的时候,不再是直接对目标方法进行调用,而是通过代理类间接调用。让不属于目标方法核心逻辑的代码从目标方法中剥离出来——解耦。调用目标方法时先调用代理对象的方法,减少对目标方法的调用和打扰,同时让附加功能能够集中在一起也有利于统一维护。
    在这里插入图片描述
    使用代理后:
    在这里插入图片描述

    ②生活中的代理
    • 广告商找大明星拍广告需要经过经纪人
    • 合作伙伴找大老板谈合作要约见面时间需要经过秘书
    • 房产中介是买卖双方的代理
    ③相关术语
    • 代理:将非核心逻辑剥离出来以后,封装这些非核心逻辑的类、对象、方法。
    • 目标:被代理“套用”了非核心逻辑代码的类、对象、方法。

    3.2.2、静态代理

    创建静态代理类:

    public class CalculatorStaticProxy implements Calculator {
    
    	// 将被代理的目标对象声明为成员变量
        private CalculatorImpl target;
    
        public CalculatorStaticProxy(CalculatorImpl target) {
            this.target = target;
        }
    
        @Override
        public int add(int i, int j) {
            int result = 0;
            try {
            	// 附加功能由代理类中的代理方法来实现
                System.out.println("[日志] add 方法开始了,参数是:" + i + "," + j);
                result = target.add(i, j);
                // 通过目标对象来实现核心业务逻辑
                System.out.println("[日志] add 方法结束了,结果是:" + result);
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
            }
            return result;
        }
    
        @Override
        public int sub(int i, int j) {
            System.out.println("[日志] sub 方法开始了,参数是:" + i + "," + j);
            int result = target.sub(i, j);
            System.out.println("[日志] sub 方法结束了,结果是:" + result);
            return result;
        }
    
        @Override
        public int mul(int i, int j) {
            System.out.println("[日志] mul 方法开始了,参数是:" + i + "," + j);
            int result = target.mul(i, j);
            System.out.println("[日志] mul 方法结束了,结果是:" + result);
            return result;
        }
    
        @Override
        public int div(int i, int j) {
            System.out.println("[日志] div 方法开始了,参数是:" + i + "," + j);
            int result = target.div(i, j);
            System.out.println("[日志] div 方法结束了,结果是:" + result);
            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
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    public class CalculatorImpl implements Calculator {
        @Override
        public int add(int i, int j) {
    //        System.out.println("[日志] add 方法开始了,参数是:" + i + "," + j);
            int result = i + j;
            System.out.println("方法内部 result = " + result);
    //        System.out.println("[日志] add 方法结束了,结果是:" + result);
            return result;
        }
        @Override
        public int sub(int i, int j) {
    //        System.out.println("[日志] sub 方法开始了,参数是:" + i + "," + j);
            int result = i - j;
            System.out.println("方法内部 result = " + result);
    //        System.out.println("[日志] sub 方法结束了,结果是:" + result);
            return result;
        }
        @Override
        public int mul(int i, int j) {
    //        System.out.println("[日志] mul 方法开始了,参数是:" + i + "," + j);
            int result = i * j;
            System.out.println("方法内部 result = " + result);
    //        System.out.println("[日志] mul 方法结束了,结果是:" + result);
            return result;
        }
        @Override
        public int div(int i, int j) {
    //        System.out.println("[日志] div 方法开始了,参数是:" + i + "," + j);
            int result = i / j;
            System.out.println("方法内部 result = " + result);
    //        System.out.println("[日志] div 方法结束了,结果是:" + result);
            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
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34

    静态代理确实实现了解耦,但是由于代码都写死了,完全不具备任何的灵活性。就拿日志功能来说,将来其他地方也需要附加日志,那还得再声明更多个静态代理类,那就产生了大量重复的代码,日志功能还是分散的,没有统一管理。
    提出进一步的需求:将日志功能集中到一个代理类中,将来有任何日志需求,都通过这一个代理类来实现。这就需要使用动态代理技术了。


    3.2.3、动态代理

    在这里插入图片描述
    生产代理对象的工厂类:

    public class ProxyFactory {
    private Object target;
    public ProxyFactory(Object target) {
    this.target = target;
    }
    public Object getProxy(){
    /**
    * newProxyInstance():创建一个代理实例
    * 其中有三个参数:
    * 1、classLoader:加载动态生成的代理类的类加载器
    * 2、interfaces:目标对象实现的所有接口的class对象所组成的数组
    * 3、invocationHandler:设置代理对象实现目标对象方法的过程,即代理类中如何重写接
    口中的抽象方法
    */
    ClassLoader classLoader = target.getClass().getClassLoader();
    Class<?>[] interfaces = target.getClass().getInterfaces();
    InvocationHandler invocationHandler = new InvocationHandler() {
    @Override
    public Object invoke(Object proxy, Method method, Object[] args)
    throws Throwable {
    /**
    * proxy:代理对象
    * method:代理对象需要实现的方法,即其中需要重写的方法
    * args:method所对应方法的参数
    * */
    Object result = null;
    try {
    System.out.println("[动态代理][日志] "+method.getName()+",参
    数:"+ Arrays.toString(args));
    result = method.invoke(target, args);
    System.out.println("[动态代理][日志] "+method.getName()+",结
    果:"+ result);
    } catch (Exception e) {
    e.printStackTrace();
    System.out.println("[动态代理][日志] "+method.getName()+",异
    常:"+e.getMessage());
    } finally {
    System.out.println("[动态代理][日志] "+method.getName()+",方法
    执行完毕");
    }
    return result;
    }
    };
    return Proxy.newProxyInstance(classLoader, interfaces,
    invocationHandler);
    }
    }
    
    • 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
    • 47

    3.2.4、测试

        @Test
        public void test(){
    
    //        CalculatorStaticProxy proxy = new CalculatorStaticProxy(new CalculatorImpl());
    //        proxy.add(1,2);
    
            ProxyFactory proxyFactory = new ProxyFactory(new CalculatorImpl());
            Calculator proxy = (Calculator) proxyFactory.getProxy();
            proxy.add(1,2);
    //        proxy.div(1,0);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

  • 相关阅读:
    维基百科是如何定义联合办公空间的?
    APIJSON自动化ORM库,后端接口和文档自动化实践整理 (一)
    如何按照一定的需求进行开发ALV报表
    系统架构设计——互联网金融的架构设计
    Java8 Stream 强大功能之统计、汇总、多字段分组和多个列汇总统计【含面试题】
    P1449 后缀表达式题解
    Python使用抽象工厂模式和策略模式的组合实现生成指定长度的随机数
    ubuntu 系统解决GitHub无法访问问题
    ❋JQuery的快速入门2 jq鼠标滚轮
    Pandas数据类型转换
  • 原文地址:https://blog.csdn.net/qq_44774198/article/details/126128842