Spring学习(7) AOP前奏之代理模式

本文阅读 3 分钟
首页 代码,Java 正文
  • 代理模式:我们需要去做一件事情,但是又不希望自己去做,这个时候就可以找个代理(中介)
  • 我们(目标对象)与中介(代理对象)不能互相转换,因为是兄弟关系img
  • 需求:实现加减乘除的计算器类
    - 在加减乘除方法中,添加日志功能(在计算之前,记录日志,在计算之后,显示结果) - img
  • 实现后发现的问题:
    - 日志代码比较分散,我们可以提取日志类 - 日志代码比较混乱,日志代码(非核心代码)和加减乘除方法(核心代码)可以写在一处
  • 总结:在核心代码中,需要日志功能,但是我们并不希望,在核心代码中添加日志代码
    - 此时:我们可以使用代理模式来解决这个问题,先把日志代码横向提取在日志类中, 然后再动态织入回到业务代码中 - img
  • 实现方式
    - 基于接口实现动态代理:JDK动态代理 - 基于继承实现动态代理:Cglib、Javassist动态代理
  • 实现动态代理关键步骤
    - 一个类:Proxy
      - 概述:Proxy代理类的基类(类似Object) - 作用:newProxyInstance():创建代理对象
    • 一个接口:InvocationHandler
      - 概述:实现动态织入效果的关键接口 - 作用:invoke(),执行invoke()方法实现动态织入效果
    • 创建类(为了实现创建代理对象的工具类)
    • 提供属性(本质上是目标对象,在实现类中实现)
    • 提供方法(创建代理对象)
    • 提供有参构造器(为了避免目标对象为空)

    接口

    public interface Calc { 
        int add(int a, int b);
    
        int sub(int a, int b);
    
        int mul(int a, int b);
    
        int div(int a, int b);
    }

    实现类

    @Component
    public class CalcImpl implements Calc{ 
        @Override
        public int add(int a, int b) { 
            int result=a+b;
            return result;
        }
    
        @Override
        public int sub(int a, int b) { 
           int result=a-b;
           return result;
        }
    
        @Override
        public int mul(int a, int b) { 
            int result= a*b;
            return result;
        }
    
        @Override
        public int div(int a, int b) { 
            int result= a/b;
            return result;
        }
    }

    日志

    public class MyLogging { 
        public static void beforeMethod(String methodName,Object[]args){ 
            System.out.println("==>Calc中"+methodName+"方法(),参数:"+ Arrays.toString(args));
    
        }
        public static void afterMethod(String methodName,Object res){ 
            System.out.println("==>Calc中"+methodName+"方法(),结果:"+ res);
        }
    
    
    }

    关键代码

    **我们要获得代理对象,前提要知道代理谁
     * @author zengyihong
     * @create 2022--07--02 17:18
     */
    public class MyProxy { 
        /** * 目标对象 */
        private Object target;
        public MyProxy(Object target){ 
            this.target=target;
        }
    
        /** * 获取目标对象的代理对象 * ClassLoader loader, 类加载器,用目标对象的类加载器 * Class<?>[] interfaces, 目标对象实现的所有接口 * InvocationHandler h */
        public Object getProxyObject(){ 
            //代理对象
            Object proxyObj=null;
            ClassLoader classLoader = target.getClass().getClassLoader();
            Class<?>[] interfaces = target.getClass().getInterfaces();
            //创建代理对象
            proxyObj =Proxy.newProxyInstance(classLoader, interfaces, new InvocationHandler() { 
                @Override
                public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { 
                    //执行之前添加日志
                    MyLogging.beforeMethod(method.getName(),args);
                    //触发目标对象的目标方法 执行哪个目标对象的方法,方法参数
                    Object res = method.invoke(target, args);
                    //执行目标方法后,添加日志
                    MyLogging.afterMethod(method.getName(),res);
                    return res;
                }
            });
            return proxyObj;
        }
    
    
    
    
    
    }

    img

    本文为互联网自动采集或经作者授权后发布,本文观点不代表立场,若侵权下架请联系我们删帖处理!文章出自:https://zengyihong.blog.csdn.net/article/details/125529770
-- 展开阅读全文 --
安全面试之XSS(跨站脚本攻击)
« 上一篇 07-24

发表评论

成为第一个评论的人

热门文章

标签TAG

最近回复