详解SpringAop开发过程中的坑

 

 😉😉 学习交流群:

✅✅1:这是孙哥suns给大家的福利!

✨✨2:我们免费分享Netty、Dubbo、k8s、Mybatis、Spring...应用和源码级别的视频资料

🥭🥭3:QQ群:583783824   📚📚  工作微信:BigTreeJava 拉你进微信群,免费领取!

🍎🍎4:本文章内容出自上述:Spring应用课程!💞💞

💞💞5:以上内容,进群免费领取呦~ 💞💞💞💞

一:AOP开发中的坑

        编程人员在常规过程中不常遇到的问题,但是一旦遇到这个问题,就一定会出错

1:代码实例

public class TestASpectProxy {
    public static void main(String[] args) {
        ApplicationContext ctx = new ClassPathXmlApplicationContext("/applicationContext3.xml");
        UserService userService = (UserService) ctx.getBean("userService");
        userService.register(new User());
        //--------------aspect log-----------
        //--------------aspect tx-----------
        //UserServiceImpl.register
        //UserServiceImpl.login
    }
}
@Aspect
public class MyAspect {
    //这是一个类切入点,给所有的都加上额外功能
    @Pointcut("execution(* *..UserServiceImpl.*(..))")
    public void myPointcut(){}
    /**
     * ProceedingJoinPoint这个等效于MethodInvocation
     * 这里写的是额外功能的部分,现在的额外功能不需要实现接口了,只需要加入注解。
     * */
    @Around(value="myPointcut()")//在这里调用切入点表达式,就完成了整合。
    public Object arround(ProceedingJoinPoint joinPoint) throws Throwable {
        System.out.println("--------------aspect log-----------");
        Object proceed = joinPoint.proceed();
        return proceed;
    }

    @Around(value="myPointcut()")
    public Object arround1(ProceedingJoinPoint joinPoint) throws Throwable {
        System.out.println("--------------aspect tx-----------");
        Object proceed = joinPoint.proceed();
        return proceed;
    }
}
public class UserServiceImpl implements UserService {
    @Override
    public void login(String username, String password) {
        System.out.println("UserServiceImpl.login");
    }

    @Override
    public void register(User user) {
        System.out.println("UserServiceImpl.register");
        this.login("suns","123456");
    }
}


        测试结果并不符合预期,login方法调用的时候额外功能并没有展示,这个就是那个坑,为什么login方法没有执行额外功能呢?当我们的调用者调用register方法的时候,我们调用的是Proxy代理对象的Register方法,加入了日志加入了事务,最终执行了这两个额外功能,没有问题,但是调用login方法的时候,是在原有功能当中调用的login方法,调用的并不是代理对象中的login方法而是调用的login原生的login方法所以没有额外功能的加入。

        这个告诉我们的道理就是:方法中调用类中原始对象的方法的的时候,那么久不会有额外功能的引入,要想使调用方法的额外功能也展示需要调用代理对象的对应的方法,而不是原始对象的对应的方法。也就是说我们需要在我们的register方法中获取到Spring的工厂对象,进而拿到我们的代理对象,进而调用我们的代理对象的login方法,然而初步的想法是在register方法中创建Spring的工厂对象,然而这是不可取的,这是重量级资源,占用大量内存,可以采取的途径是让我们的UserServiceImpl 实现ApplicationContextAware接口,Aware的含义是知道的意思,这个接口中有一个方法是setApplicationContext,通过这个方法入参是工厂对象,Spring容器启动时会回调这个方法,将引用赋值给这个这个方法,所以我们实现方法之后,存一份就好了。

public class UserServiceImpl implements UserService, ApplicationContextAware {
    private ApplicationContext ctx;

    @Override
    public void login(String username, String password) {
        System.out.println("UserServiceImpl.login");
    }

    @Override
    public void register(User user) {
        System.out.println("UserServiceImpl.register");
        UserService userService = (UserService) ctx.getBean("userService");//userService是代理对象
        userService.login("suns","123456");
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.ctx = applicationContext;
    }
}


2:测试结果

public class TestASpectProxy {
    public static void main(String[] args) {
        ApplicationContext ctx = new ClassPathXmlApplicationContext("/applicationContext3.xml");
        UserService userService = (UserService) ctx.getBean("userService");
        userService.register(new User());
        //--------------aspect log-----------
        //--------------aspect tx-----------
        //UserServiceImpl.register
        //    --------------aspect log-----------
        //--------------aspect tx-----------
        //UserServiceImpl.login

    }
}
//实现了被调用的时候也有这个额外功能的实现。


        在同一个业务类中,进行业务方法间的相互调用的时候,只有最外层的方法,加入了额外功能了。

        内部的方法通过普通的方式进行调用,并没有额外功能,都是原始方法,那么如果想让内层的方法也调用代理对象的方法,就需要通过ApplicationContextAware获得工厂,进而获得代理对象

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/213609.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Kubernetes实战(六)-多系统架构容器镜像构建实战

1 背景 最近在一个国产化项目中遇到了这样一个场景,在同一个 Kubernetes 集群中的节点是混合架构的,即其中某些节点的 CPU 架构是 x86 的,而另一些节点是 ARM 的。为了让镜像在这样的环境下运行,一种最简单的做法是根据节点类型为…

使用Java语言实现字母之间的大小写转换

这个类的作用为实现字母之间的大小写转换,通过加减32来完成。 输入的代码 import java.util.Scanner; public class WordChangeDemo {public static void main(String[] args){try (Scanner in new Scanner(System.in)) {System.out.println("请输入您要进…

springboot单元测试关闭日志

在logback中关闭日志 在test目录下新建文件夹resources&#xff0c;新增文件logback-test.xml文件 在logback-test.xml 文件中&#xff0c;添加内容&#xff1a; <?xml version"1.0" encoding"UTF-8"?> <configuration><include resourc…

接口测试的简介及测试用例的设计

一&#xff0c;什么是接口 接口测试是测试系统组件间接口的一种测试。接口测试主要用于检测外部系统与系统之间以及内部各个子系统之间的交互点。测试的重点是要检查数据的交换&#xff0c;传递和控制管理过程&#xff0c;以及系统间的相互逻辑依赖关系等。 二&#xff0c;接口…

《python每天一小段》--(1)与GPT-3.5-turbo 模型进行对话

对话如图&#xff1a; 配置环境变量 APIKey如何获得这边不做说明 在Windows操作系统中&#xff0c;你可以按照以下步骤设置环境变量&#xff1a; 打开“控制面板”。在控制面板中&#xff0c;选择“系统和安全”。选择“系统”。在系统窗口中&#xff0c;选择“高级系统设置”…

6-3 求3*3整数矩阵对角线元素之和

#include<stdio.h>int main(){int a[3][3],sum0;int i ,j;printf("输入元素&#xff1a;\n");for(i0;i<3;i)for(j0;j<3;j)scanf("%d",&a[i][j]);for(i0;i<3;i)sumsuma[i][i];printf("总和为&#xff1a;%d",sum);return 0;}

Python:私人定制密码保险库 - Vault

简介&#xff1a;Vault是一种用于安全访问机密的工具。秘密是您想要严格控制访问权限的任何内容&#xff0c;例如API密钥、密码、证书等等。Vault为任何机密提供了统一的界面&#xff0c;同时提供了严格的访问控制并记录了详细的审核日志。 历史攻略&#xff1a; Python&…

C++基础 -36- 模板之模板函数

模板函数格式 template <class T> void allexchange(T a,T b) {T c;c*a;*a*b;*bc; }模板函数可以增强函数的通用性 举例说明&#xff0c;使用一个模板函数实现了两个的函数的功能 #include "iostream"using namespace std;void myexchangeint(int* a,int* …

Mac卸载、安装Python

卸载 说明 对于删除 Python&#xff0c;我们首先要知道其具体都安装了什么&#xff0c;实际上&#xff0c;在安装 Python 时&#xff0c;其自动生成&#xff1a; Python framework&#xff0c;即 Python 框架&#xff1b;Python 应用目录&#xff1b;指向 Python 的连接。 …

【Tkinter 入门教程】

【Tkinter 入门教程】 1. Tkinter库的简介&#xff1a;1.1 GUI编程1.2 Tkinter的定位 2. Hello word! 程序起飞2.1 第⼀个程序2.2 字体颜色主题 3. 组件讲解3.1 tkinter 的核⼼组件3.2 组件的使⽤3.3 标签Label3.3.1 标签显示内容3.3.2 多标签的应⽤程序3.3.3 总结 3.4 按钮but…

leetcode 201 数字范围按位与

leetcode 201 题目题解代码 题目 给你两个整数 left 和 right &#xff0c;表示区间 [left, right] &#xff0c;返回此区间内所有数字 按位与 的结果&#xff08;包含 left、right 端点&#xff09;。 具体示例如下&#xff1a; 题解 本题是一个在思维上的方法&#xff0c;不…

Ant Design Pro 框架设置API Token拦截器的功能

分享记录一个解决方法&#xff0c;希望对大家有帮助。 找到文件&#xff0c;然后定义一个方法。最后调用一下即可。 代码我也给你贴上了。 // 获取token 拦截方法 const setTokenRequest (config: any) > {const token 30|eh5GNXWRe5rO4XLjbbnqy132RABfiKqI338EoIhqc790a…

sourceTree的下载和安装

sourceTree的下载和安装 一、概述 SourceTree 是一款免费的 Git 和 Hg 客户端管理工具&#xff0c;支持 Git 项目的创建、克隆、提交、push、pull 和合并等操作。它拥有一个精美简洁的界面&#xff0c;大大简化了开发者与代码库之间的 Git 操作方式&#xff0c;这对于不熟悉 …

java学习part32StringBuffer和StringBuilder

Java中的值传递和引用传递&#xff08;详解&#xff09; - 知乎 (zhihu.com) 146-常用类与基础API-StringBuffer与StringBuilder的源码分析、常用方法_哔哩哔哩_bilibili 1. 2.扩容机制 不够用&#xff1a;长度为 原长度*22&#xff1b;如果还不够&#xff0c;那么就扩容到目…

STM32踩坑--串口发送乱码

一、发现问题 今天在STM32F407新板子上测试串口时&#xff0c;发现发送数据一直乱码。 二、解决问题 针对STM32F407系列校准PLLCLK时钟&#xff1a; ①由 时钟树 可以看出PLLCLKHSE&#xff08;高速外部时钟&#xff09;*N/(M*P)。因为SYSTICK一般取最高的时钟168M&#xff…

【Linux】第二十五站:深入理解文件系统

文章目录 一、前言二、认识硬件----磁盘1.基本介绍2.磁盘的存储构成3.磁盘的逻辑结构4.回归到硬件 三、文件系统1.划分2.Block group(1)Data blocks(2)inode Table(3)Block Bitmap(4)inode Bitmap(5)Group Descriptor Table(GDT)(6)Super Block 3.总结4.一些其他问题5.如何理解…

C语言--求一个十进制整数中1的个数

一.题目描述⭐ 求一个十进制整数中1的个数 比如&#xff1a; 输入:10201 输出&#xff1a;2 &#xff08;这个数字中1的个数是2&#xff09; 二.思路分析⭐ 数字类的问题我们可以用取模&#xff0c;或者取余运算。 首先定义一个计数器&#xff0c;用来统计1的个数。 输入数字…

《管家婆》辉煌2005+(V4.0)简单教程

《管家婆》辉煌2005&#xff08;V4.0&#xff09;简单教程 呉師傅 运行环境&#xff1a;   操作系统推荐使用Win2000&#xff08;32位&#xff09;、WinXP&#xff08;32位&#xff09;、Win7&#xff08;位&#xff09; 兼容&#xff1a;Win7&#xff08;64位&#xff09…

【毕业设计】基于雷达与深度学习的摔倒检测——微多普勒效应

运动物体的微多普勒效应为人体动作识别提供了可能&#xff0c;基于雷达的居家检测具有良好的隐私保护性&#xff0c;且不易受环境因素影响&#xff08;如光照、温度等&#xff09;&#xff0c;近年来已受到国内外学者的广泛关注。由于雷达信号的非平稳特性&#xff0c;通过短时…

html电子签名

html电子签名 html5实现手写签名板&#xff0c;点击保存即可生成base64格式的图片 使用H5自带的canvas&#xff0c;无需引入js无需引入别的js 效果图 html代码 <!DOCTYPE html> <html> <head><meta http-equiv"Content-Type" content"…