详解SpringAop开发过程中的坑

news2025/2/25 16:00:39

 

 😉😉 学习交流群:

✅✅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获得工厂,进而获得代理对象

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

在 ArcGIS 软件中添加左斜宋体(东体)的方法与步骤

河流水系在作图时一般设置为左斜宋体(东体)、蓝色,比如黄河、青海湖等,如下图所示: 标准地图水系注记 下面讲解如何在 ArcGIS 软件中添加左斜宋体(东体),首先需要下载左斜宋体&#…

使用 OpenFunction 在任何基础设施上运行 Serverless 工作负载

作者: 霍秉杰:KubeSphere 可观测性、边缘计算和 Serverless 团队负责人,Fluent Operator 和 OpenFunction 项目的创始人,还是多个可观测性开源项目包括 Kube-Events、Notification Manager 等的作者,热爱云原生技术&am…

STM32F407-14.3.8-01强制输出模式

强制输出模式 在输出模式(TIMx_CCMRx 寄存器中的 CCxS② 位 00)下,可直接由软件将每个输出比较信号(OCxREF④ 和 OCx⑥/OCxN⑦)强制设置为有效电平或无效电平,而无需考虑输出比较寄存器和计数器之间的任何…

springboot 整合 Spring Security 上篇

1.创建springBoot 项目工程(spring6.0的底层、JDK17) 1.添加依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-security</artifactId></dependency>配置完成启动访问controller会出现登录…

JS 实现一键复制文本内容

1、演示&#xff1a; 2、代码 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>一键复制</title&g…

如何用Java实现扑克牌(附源码)

目录 一.扑克牌的数据结构 二.买牌(扑克牌的初始化) 三.洗牌 四.发牌 五.完整代码 Card.java CardList.java 六.测试 输出结果 一.扑克牌的数据结构 首先&#xff0c;扑克牌是一幅一幅的&#xff0c;除去大小王以外一共有52张&#xff0c;我们可以考虑用数组来存储…

常用装备生产ERP有哪几种?有哪些作用

装备生产业务涉及原材料采购、车间排产、班组生产评估、派工单、接单报价、委外发料、库存盘点、设备台账、图纸设计等诸多环节&#xff0c;而各环节数据的共享问题普遍存在于装备生产企业内部&#xff0c;同时也直接影响企业的生产效率和整体效益等。 企业外部环境的变化和行…

linux安装KingbaseES(人大金仓数据库)

KingbaseES V8 数据库简介 金仓数据库管理系统[简称:KingbaseES]是北京人大金仓信息技术股份有限公司[简称人大金仓]的核心产品&#xff0c;具有大型通用、"三高"&#xff08;高可靠、高性能、高安全&#xff09;、"三易"&#xff08;易管理、易使用、易扩…

记录华为云服务器(Linux 可视化 宝塔面板)-- 防火墙篇

文章目录 前言安装防火墙防火墙设置防火墙操作1.设置开机启动防火墙2.查看防火墙开放哪些端口3.重载防火墙配置&#xff08;修改配置后重新启动才生效&#xff09;4.查看防火墙状态5.开启防火墙6.关闭防火墙 若遇到无法开启查询已开放的端口查询端口是否开放&#xff08;80&…

springBoot整合task

springBoot整合task 文章目录 springBoot整合task开开关设置任务&#xff0c;并设置执行周期定时任务的相关配置 开开关 设置任务&#xff0c;并设置执行周期 Component public class MyBean {Scheduled(cron "0/1 * * * * ?")public void print(){System.out.prin…

TCP连接为什么是三次握手,而不是两次和四次

答案 阻止重复的历史连接同步初始序列号避免资源浪费 原因 阻止重复的历史连接&#xff08;首要原因&#xff09; 考虑这样一种情况&#xff1a; 客户端现在要给服务端建立连接&#xff0c;向服务端发送了一个SYN报文段&#xff08;第一次握手&#xff09;&#xff0c;以表示请…

Oracle(2-10) User-Managed Backups

文章目录 一、基础知识1、Terminology 术语2、User-Managed Backup/Recovery 用户管理的备份/恢复3、Get DB File Information 获取数据库文件信息4、Consistent Whole DB Backup 一致的整个数据库备份冷备份热备份 二、基础操作1、查找需要备份的各种文件2、整备操作冷备份热备…

【Element-ui】Link 文字链接 与 Radio 单选框

文章目录 前言一、Link 文字链接1.1 基础用法1.2 禁用状态1.3 下划线1.4 图标 二、Radio 单选框2.1 基础用法2.2 禁用状态2.3 单选框组2.4 按钮样式2.5 带有边框2.6 Radio Eventsinput事件 2.7 Radio-group Attributes 总结 前言 在前端开发中&#xff0c;用户界面的元素设计和…

Certum SSL证书

为了确保在线交易的安全性&#xff0c;以及保护敏感信息免受网络威胁&#xff0c;使用SSL&#xff08;Secure Socket Layer&#xff09;证书成为了必要选择。其中&#xff0c;波兰认证机构Certum提供的SSL证书以其高度的安全性和可信赖性&#xff0c;得到了全球用户的广泛认可。…

基于运算放大器的电压采集电路

一、运算放大器 运放推导的两个重要概念&#xff1a;虚短、虚断。 1、差分放大器 以差分放大器为例进行推导分析。 虚断–运放的"-“端、”“端的引脚电流接近为0&#xff1b; 根据基尔霍夫电流定律可知&#xff1a;iR1iRF&#xff0c;iR2iR3&#xff1b; iR1(Ui1-(V-…

二分查找边界问题——排序数组找元素第一次出现和最后一次出现

二分查找的边界逼近问题&#xff1a; 下面的代码&#xff0c;第一个函数会向左边界逼近&#xff0c;第二个函数会像右边界逼近&#xff01; 考虑left5,right6这种情况&#xff0c;如果5&#xff0c;6的值都是满足的条件的怎么办&#xff1f; 如果mid(leftright1)/2&#xff0c;…

Qt将打印信息输出到文件

将打印信息&#xff08;qDebug、qInfo、qWarning、qCritial等&#xff09;输出到指定文件来以实现简单的日志功能。 #include "mainwindow.h" #include <QApplication> #include <QLoggingCategory> #include <QMutex> #include <QDateTime>…

面试数据库八股文十问十答第二期

面试数据库八股文十问十答第二期 作者&#xff1a;程序员小白条&#xff0c;个人博客 相信看了本文后&#xff0c;对你的面试是有一定帮助的&#xff01; ⭐点赞⭐收藏⭐不迷路&#xff01;⭐ 1.MySQL的主从复制 MySQL的主从复制是什么&#xff1f;MySQL主从复制是一种常见的…

Hdoop学习笔记(HDP)-Part.09 安装OpenLDAP

目录 Part.01 关于HDP Part.02 核心组件原理 Part.03 资源规划 Part.04 基础环境配置 Part.05 Yum源配置 Part.06 安装OracleJDK Part.07 安装MySQL Part.08 部署Ambari集群 Part.09 安装OpenLDAP Part.10 创建集群 Part.11 安装Kerberos Part.12 安装HDFS Part.13 安装Ranger …

Java语法之字符串类型

String类 在Java中&#xff0c;使用String类定义字符串类型&#xff0c;如下&#xff1a; String s1"hello";System.out.println(s1); 字符串拼接 只要s1s2即可 在字符串中&#xff0c;如果俩个字符串进行相加&#xff0c;那他就是字符串拼接的意思 补充 如上&am…