Spring-动态代理深入了解

2023-08-05 21:01:53

😀前言
本篇的Spring-AOP系类文章第二篇扩展了Spring-动态代理然后开发了简易的AOP类

🏠个人主页:尘觉主页
在这里插入图片描述

🧑个人简介:大家好,我是尘觉,希望我的文章可以帮助到大家,您的满意是我的动力😉😉

在csdn获奖荣誉: 🏆csdn城市之星2名
⁣⁣⁣⁣ ⁣⁣⁣⁣ ⁣⁣⁣⁣ ⁣⁣⁣⁣ ⁣⁣⁣⁣ ⁣⁣⁣⁣ ⁣⁣⁣⁣ ⁣⁣⁣⁣ 💓Java全栈群星计划top前5
⁣⁣⁣⁣ ⁣⁣⁣⁣ ⁣⁣⁣⁣ ⁣⁣⁣⁣ ⁣⁣⁣⁣ ⁣⁣⁣⁣ ⁣⁣⁣⁣ ⁣⁣⁣⁣ 🤗 端午大礼包获得者

💕欢迎大家:这里是CSDN,我总结知识的地方,欢迎来到我的博客,感谢大家的观看🥰
如果文章有什么需要改进的地方还请大佬不吝赐教 先在次感谢啦😊

🥰Spring-动态代理深入了解

😁代码演示–动态代理深入

需求说明

  1. 有一个 SmartAnimal 接口,可以完成简单的加减法, 要求在执行 getSum()和 getSub() 时,输出执行前,执行过程,执行后的日志输出

💖输出结果

日志-方法名-getSum-参数 10.0 2.0
方法内部打印 result = 12.0
日志-方法名-getSum-结果 result= 12.0


日志-方法名-getSub-参数 10.0 2.0
方法内部打印 result = 8.0
日志-方法名-getSub-结果 result= 8

创建步骤

  1. 创建接口 SmartAnimalable.java
public interface SmartAnimalable {
    //求和
    float getSum(float i, float j);
    //求差
    float getSub(float i, float j);
}
  1. 实现类SmartDog
public class SmartDog implements SmartAnimalable {
    @Override
    public float getSum(float i, float j) {
        //System.out.println("日志-方法名-getSum-参数 " + i + " " + j);
        float result = i + j;
        System.out.println("方法内部打印result = " + result);
        //System.out.println("日志-方法名-getSum-结果result= " + result);
        return result;
    }

    @Override
    public float getSub(float i, float j) {
        //System.out.println("日志-方法名-getSub-参数 " + i + " " + j);
        float result = i - j;
        System.out.println("方法内部打印result = " + result);
        //System.out.println("日志-方法名-getSub-结果result= " + result);
        return result;
    }
}
  1. 创建MyProxyProvider类

注意这里就没有使用上面直接new一个对象来调用了而是直接使用反射

这里也考虑了出现异常的问题

执行思路

定义我们要执行的目标对象, 该对象需要实现SmartAnimalable

构造器

方法, 可以返回代理对象,该代理对象可以执行目标对象

  • 先到的类加载器/对象

  • 得到要执行的目标对象的接口信息

  • 创建InvocationHandler

最后 创建代理对象并返回

public class MyProxyProvider {

    //定义我们要执行的目标对象, 该对象需要实现SmartAnimalable
    private SmartAnimalable target_obj;

    //构造器
    public MyProxyProvider(SmartAnimalable target_obj) {
        this.target_obj = target_obj;
    }

    //方法, 可以返回代理对象,该代理对象可以执行目标对象
    public SmartAnimalable getProxy() {

        //1. 先到的类加载器/对象
        ClassLoader classLoader = target_obj.getClass().getClassLoader();

        //2. 得到要执行的目标对象的接口信息
        Class<?>[] interfaces = target_obj.getClass().getInterfaces();

        //3. 创建InvocationHandler
        InvocationHandler invocationHandler = new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                Object result = null;
                try {
                    System.out.println("方法执行前-日志-方法名-" + method.getName() + "-参数 "
                            + Arrays.asList(args)); //这里从AOP看,就是一个横切关注点-前置通知
                    //使用反射调用方法
                    result = method.invoke(target_obj, args);
                    System.out.println("方法执行正常结束-日志-方法名-" + method.getName() + "-结果result= "
                            + result);//从AOP看, 也是一个横切关注点-返回通知

                } catch (Exception e) {
                    e.printStackTrace();
                    //如果反射执行方法时,出现异常,就会进入到catch{}
                    System.out.println("方法执行异常-日志-方法名-" + method.getName()
                            + "-异常类型=" + e.getClass().getName());//从AOP看, 也是一个横切关注点-异常通知
                } finally {//不管你是否出现异常,最终都会执行到finally{}
                    //从AOP的角度看, 也是一个横切关注点-最终通知
                    System.out.println("方法最终结束-日志-方法名-" + method.getName());
                }

                return result;
            }
        };

        //创建代理对象
        SmartAnimalable proxy =
                (SmartAnimalable)Proxy.newProxyInstance(classLoader, interfaces, invocationHandler);
        return proxy;
    }
}
创建测试类
@Test
    public void smartDogTestByProxy() {

        SmartAnimalable smartAnimalable = new SmartDog();

        MyProxyProvider myProxyProvider =
                new MyProxyProvider(smartAnimalable);

        //我们返回了代理对象
        SmartAnimalable proxy =
                myProxyProvider.getProxy();

        proxy.getSum(10, 2);
        System.out.println("====================");
        proxy.getSub(10, 2);

    }

💞 ● 问题提出

  1. 在 MyProxyProvider.java 中, 我们的输出语句功能比较弱,在实际开发中,我们希望是 以一个方法的形式,嵌入到真正执行的目标方法前

使用土方法解决前面的问题

把输出语句抽出来在上面形成一个方法

创建步骤

  1. 创建MyProxyProvider
//我们一个方法,在目标对象执行前执行
    public void before(Object proxy, Method method, Object[] args) {
       System.out.println("before-方法执行前-日志-方法名-" + method.getName() + "-参数 "
               + Arrays.asList(args)); //这里从AOP看,就是一个横切关注点-前置通知
    }

    //我们一个方法,在目标对象执行后执行
    public void after(Method method, Object result) {
       System.out.println("after-方法执行正常结束-日志-方法名-" + method.getName() + "-结果result= "
               + result);//从AOP看, 也是一个横切关注点-返回通知
    }
public SmartAnimalable getProxy() {

        //1. 先到的类加载器/对象
        ClassLoader classLoader = target_obj.getClass().getClassLoader();

        //2. 得到要执行的目标对象的接口信息
        Class<?>[] interfaces = target_obj.getClass().getInterfaces();

        //3. 创建InvocationHandler
        InvocationHandler invocationHandler = new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                Object result = null;
                try {

                    before(proxy, method, args);


                    //使用反射调用方法
                    result = method.invoke(target_obj, args);

                    after(method, result);
                } catch (Exception e) {
                    e.printStackTrace();
                    //如果反射执行方法时,出现异常,就会进入到catch{}
                    System.out.println("方法执行异常-日志-方法名-" + method.getName()
                            + "-异常类型=" + e.getClass().getName());//从AOP看, 也是一个横切关注点-异常通知
                } finally {//不管你是否出现异常,最终都会执行到finally{}
                    //从AOP的角度看, 也是一个横切关注点-最终通知
                    System.out.println("方法最终结束-日志-方法名-" + method.getName());
                }

                return result;
            }
        };

        //创建代理对象
        SmartAnimalable proxy =
                (SmartAnimalable) Proxy.newProxyInstance(classLoader, interfaces, invocationHandler);
        return proxy;
    }
}

该方法问题分析:

耦合度高

❤️‍🔥对土方法解耦-开发简易的 AOP 类

创建步骤

  1. 创建WyxAOP.java
/**
 * 自己编写一个一个极简的AOP类
 */
public class WyxAOP {

    //我们一个方法,在目标对象执行前执行
    public static void before(Object proxy, Method method, Object[] args) {
        System.out.println("WyxAOP-方法执行前-日志-方法名-" + method.getName() + "-参数 "
                + Arrays.asList(args)); //这里从AOP看,就是一个横切关注点-前置通知
    }

    //我们一个方法,在目标对象执行后执行
    public static void after(Method method, Object result) {
        System.out.println("WyxAOP-方法执行正常结束-日志-方法名-" + method.getName() + "-结果result= "
                + result);//从AOP看, 也是一个横切关注点-返回通知
    }
}
  1. 修改MyProxyProvider
 public SmartAnimalable getProxy() {

        //1. 先到的类加载器/对象
        ClassLoader classLoader = target_obj.getClass().getClassLoader();

        //2. 得到要执行的目标对象的接口信息
        Class<?>[] interfaces = target_obj.getClass().getInterfaces();

        //3. 创建InvocationHandler
        InvocationHandler invocationHandler = new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                Object result = null;
                try {

                    WyxAOP.before(proxy, method, args);

                    //使用反射调用方法
                    result = method.invoke(target_obj, args);

                   WyxAOP.after(method, result);

                } catch (Exception e) {
                    e.printStackTrace();
                    //如果反射执行方法时,出现异常,就会进入到catch{}
                    System.out.println("方法执行异常-日志-方法名-" + method.getName()
                            + "-异常类型=" + e.getClass().getName());//从AOP看, 也是一个横切关注点-异常通知
                } finally {//不管你是否出现异常,最终都会执行到finally{}
                    //从AOP的角度看, 也是一个横切关注点-最终通知
                    System.out.println("方法最终结束-日志-方法名-" + method.getName());
                }

                return result;
            }
        };

        //创建代理对象
        SmartAnimalable proxy =
                (SmartAnimalable) Proxy.newProxyInstance(classLoader, interfaces, invocationHandler);
        return proxy;
    }
}
完成测试
    @Test
    public void smartDogTestByProxy() {

        SmartAnimalable smartAnimalable = new SmartDog();

        MyProxyProvider myProxyProvider =
                new MyProxyProvider(smartAnimalable);

        //我们返回了代理对象
        SmartAnimalable proxy =
                myProxyProvider.getProxy();

        proxy.getSum(10, 2);
        System.out.println("====================");
        proxy.getSub(10, 2);

    } 

😄总结

本篇总结了Spring-动态代理然后开发了简易的AOP类使更容易理解

😍Spring-AOP系类文章
第一篇-> Spring-AOP的基本介绍以及通过先动态代理方式实现

😁热门专栏推荐
想学习vue的可以看看这个
java基础合集
数据库合集
redis合集
nginx合集
linux合集
等等等还有许多优秀的合集在主页等着大家的光顾感谢大家的支持

🤔欢迎大家加入我的社区 尘觉社区

文章到这里就结束了,如果有什么疑问的地方请指出,诸佬们一起来评论区一起讨论😁
希望能和诸佬们一起努力,今后我们一起观看感谢您的阅读🍻
如果帮助到您不妨3连支持一下,创造不易您们的支持是我的动力🤞

更多推荐

研究报告:周界警戒AI算法+视频智能分析在安全生产场景中的应用

长期以来,周界防范安防系统在大型园区、工厂、社区、机场、火车站站台、重点单位等领域应用较为广泛和常见。随着AI人工智能等新兴技术的快速发展与落地应用,通过AI智能检测与视频智能分析技术,现代化的周界安防系统可以做到全天候快速、准确地发现入侵等异常事件,并及时报警遏制。今天我们来介绍下旭帆科技安全生产周界警戒AI算法的具

Qt使用I.MX6U开发板上的按键(原理:将电脑键盘方向键↓在Qt中的枚举值与开发板中按键定义的枚举值一致,这样电脑端测试效果就与开发板的一致)

在上篇介绍了Qt点亮I.MX6U开发板的一个LED,对于Qt控制I.MX6U开发板的一个蜂鸣器原理也是一样的,就不做详细介绍,具体可参考Qt控制I.MX6U开发板的一个蜂鸣器,本篇介绍Qt使用I.MX6U开发板上的按键的相关内容。文章目录1.开发板硬件图及板卡按键在电脑键盘中的对应原理2.出厂内核设备树中注册的按键3.

基于TensorFlow+CNN+协同过滤算法的智能电影推荐系统——深度学习算法应用(含微信小程序、ipynb工程源码)+MovieLens数据集(一)

目录前言总体设计系统整体结构图系统流程图运行环境Python环境TensorFlow环境方法一方法二后端服务器Django环境配置微信小程序环境相关其它博客工程源代码下载其它资料下载前言本项目专注于MovieLens数据集,并采用TensorFlow中的2D文本卷积网络模型。它结合了协同过滤算法来计算电影之间的余弦相似

人工智能安全-5-网络入侵检测

0提纲概述数据集数据预处理特征工程天池AI上的实践棘手问题1概述入侵检测是网络安全中的经典问题,入侵是指攻击者违反系统安全策略,试图破坏计算资源的完整性、机密性或可用性的任何行为。不管是哪种类型的入侵检测系统(IDS),其工作过程大体是相同的,可以分为三个主要的环节,即信息收集、分类检测和决策,其中,分类检测和决策环节

Git操作

前期准备:1、安装2、身份认证gitconfig--globaluser.name"your_username"gitconfig--globaluser.emailyour_email@domain.comgitconfig--list查看所有配置常见的Git命令gitstatus.命令用于显示工作目录和暂存区的状态

React useRequest解读

源码结构:可以看到虽然是一个hooks(具有一定功能且具备状态的单一函数)但是各种文件功能分得也是很细的,方便抽离和复用useRequest.ts抽离的原则还是单一功能原则可以看出真正的hooks实现是在Implement里对于类型type的引入我们需要显示声明这是importtypeuseRequestImpleme

华清 Qt day5 9月21

QT+=coreguisqlnetwork/*****************************************************************/#ifndefWIDGET_H#defineWIDGET_H#include<QWidget>#include<QWidget>#include

为何学linux及用处

目前企业使用的操作系统无非就是国产类的,windows和linux类。我们要提升自己的技能,需要学习这两款。我记得在大学时期,学习过windows以及linux,但当时觉得又不常用,就学的模棱两可。毕业之后,你会发现,其实这两种操作系统是很主流的。为什么学?下面就是一些工作中遇到的例子分享一下。我记得在企业中有次遇到数

【python第7课 实例,类】

文章目录一、实例1.1实例的变量1.2实例方法1.3构造方法1.4析构函数1.4预置实例属性:二,类1.1类变量1.2类方法1.3静态方法1.4类属性的增删改查一、实例1.1实例的变量使用示例classdog:def__init__(self,k,c,a):self.kinds=kself.color=cself.ag

【Hash表】两数之和-力扣 1 题

💝💝💝欢迎来到我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。推荐:kuan的首页,持续学习,不断总结,共同进步,活到老学到老导航檀越剑指大厂系列:全面总结java核心技术点,如集合,jvm,并发编程redis,kaf

Docker笔记

安装卸载旧版本以及相关的依赖项sudoyumremovedocker\docker-client\docker-client-latest\docker-common\docker-latest\docker-latest-logrotate\docker-logrotate\docker-engine安装所需的软件包

热文推荐