【Spring进阶系列丨第八篇】Spring整合junit 面向切面编程(AOP)详解

文章目录

  • 一、Spring整合junit
    • 1.1、导入spring整合junit的jar
    • 1.2、在测试类上添加注解
    • 1.3、说明
  • 二、面向切面编程(AOP)
    • 2.1、问题引出
    • 2.2、AOP
      • 2.2.1、概念
      • 2.2.2、作用
      • 2.2.3、优势
      • 2.2.4、实现方式
      • 2.2.5、专业术语
        • 2.2.5.1、连接点
        • 2.2.5.2、切入点
        • 2.2.5.3、通知/增强
        • 2.2.5.4、织入
        • 2.2.5.5、切面
        • 2.2.5.6、引介【了解】
  • 好书推荐

在这里插入图片描述

一、Spring整合junit

1.1、导入spring整合junit的jar

<dependency>
     <groupId>org.springframework</groupId>
     <artifactId>spring-test</artifactId>
     <version>5.2.1.RELEASE</version>
     <scope>test</scope>
</dependency>

1.2、在测试类上添加注解

@ContextConfiguration(classes = {SpringMainConfig.class})
@RunWith(SpringJUnit4ClassRunner.class)
public class ConditionalTest {

    @Autowired
    private Pig pig;

    @Test
    public void testPig() throws Exception{

        System.out.println(pig);
    }
}

1.3、说明

​ @ContextConfiguration注解需要注意的细节是:

  • classes:指定的是主配置类的字节码
  • locations:指定xml文件的位置

二、面向切面编程(AOP)

2.1、问题引出

​ 首先来看一个问题,假如我现在有一个UserServiceImpl用户业务类,其中呢,有一个保存用户的方法,即:

public class UserServiceImpl {
  	// 保存用户
    public void save(User user){
 		// 调用Dao新增用户
    }
}

​ 现在的需求是:我要在保存用户之前新增事务的功能,你可能会这么做:

public void save(User user){
        
   // 1、新增事务功能代码
   // 调用Dao新增用户
}

​ 现在的需求又变了,我要在保存用户之前不仅新增事务功能了,还要添加日志功能了,你可能又会这么做:

public void save(User user){
        
   // 2、新增记录日志功能代码
   // 1、新增事务功能代码
   // 调用Dao新增用户
}

​ 现在的需求又变了,我要在保存用户之前不仅新增事务功能了,日志功能了,还要增加开始执行保存用户方法的开始时间的功能了,你可能又会这么做:

public void save(User user){
    // 3、新增统计开始执行保存用户方法的开始时间功能
   	// 2、新增记录日志功能代码
   	// 1、新增事务功能代码
   	// 调用Dao新增用户
}

​ 现在的需求又变了,我要在保存用户之前不仅新增事务、日志功能、统计方法开始执行时间,还要新增用户是否有权限访问这个方法功能,你可能又会这么做:

public void save(User user){
     // 4、新增判断用户是否有权限功能
     // 3、新增统计开始执行保存用户方法的开始时间功能
     // 2、新增记录日志功能代码
     // 1、新增事务功能代码
     // 调用Dao新增用户
}

​ 需求又在一直改变改变着,可能忽然领导突然哪一天大腿一拍,说这些新增的功能都不要了,好,我们把我们辛苦写的代码全部注释了,也可能一气之下全删了;又过了几天,领导又抽风了,说我们需要新增事务和权限,好,我们又吭哧吭哧的去改代码了;…领导反复抽风,我们反复改反复改…最后我们顶不住压力,自杀了。

​ 出现这个问题的原因在于:反复改需求,而这些需求与我们真正要保存用户的业务逻辑关系不大,同时,我们还应该需要考虑到的是:我们的系统中可能不仅仅只有用户模块,还有商品模块,订单模块,分类模块等等。而这些模块在保存相应的数据的时候,都有可能需要新增事务、日志、时间统计、权限等功能。那么如果我们对保存的数据方法都全部写一遍新增事务功能、新增日志功能、新增时间统计功能、新增权限功能,这样的代码无疑是很臃肿的,而且是很难维护的,想到这里,你可能会这么做,把公共的代码抽取出来,可能这么干:

public class BaseService {
    
    // 新增事务
    public void transaction(){
        System.out.println("事务功能");
    }
    
    // 新增日志
    public void log(){
        System.out.println("日志功能");
    }
}
public class UserServiceImpl extends BaseService{
    public void save(User user){
        super.log();
        super.transaction();
        // 调用Dao新增用户
    }
}

​ 解决方案:把公共代码抽取到一个父类的BaseService,让具体的模块Service继承BaseService,然后调用父类的功能,这样做即:通过继承的方式实现对业务方法的功能的增强。

​ 但是这样做还有一个问题,虽然我们其他模块也需要此功能时,可以采用继承的方式来做,但是一个很严重的问题是:我们的业务功能在去调用的时候,对业务功能的增强实际上还是硬编码了。还是没有解决方便维护的问题,那我们期望能够解决的问题是:能否“神不知鬼不觉”的在不改变源代码的情况下去扩展功能呢? 答案肯定是可以的,那这就是AOP,同时,这个也是我们学习AOP的原因所在,也是AOP的作用所在。

在这里插入图片描述

​ 从上图可以看出,如果从系统的横向角度来看,我们的权限功能,日志功能,事务功能是把系统的各个模块中的各个业务方法在执行之前从前面拦截了,好像拿了一把刀把一个完整的苹果切成一半,形成了一个切面。这个也就是=="面向切面编程==中切面的含义。

2.2、AOP

2.2.1、概念

​ AOP:全称是 Aspect Oriented Programming 即:面向切面编程/面向方面编程。AOP不是一项新的技术,是OOP(面向对象编程)技术的补充,是OOP的延续,同时也是Spring最重要的内容之一。

​ 简单来说,AOP就是把我们程序重复的代码抽取出来,在需要执行的时候,使用代理技术,在不修改源码的基础上,对我们的已有方法进行增强。

​ Spring框架的AOP机制可以让开发者把业务流程中的通用功能抽取出来,单独编写功能代码。在业务流程执行过程中,Spring框架会根据业务流程要求,自动把独立编写的功能代码切入到流程的合适位置。

2.2.2、作用

​ 在程序运行期间,不修改源码对已有方法进行增强。

2.2.3、优势

  • 减少重复代码
  • 提高开发效率
  • 维护方便

2.2.4、实现方式

动态代理

2.2.5、专业术语

2.2.5.1、连接点

​ 全英叫:Joinpoint。所谓连接点是指那些被拦截到的点。在 spring 中,这些点指的是方法,因为 spring 只支持方法类型的连接点。

2.2.5.2、切入点

​ 全英叫:Pointcut。所谓切入点是指我们要对哪些 Joinpoint 进行拦截。

2.2.5.3、通知/增强

​ 全英叫:Advice。所谓通知/增强是指拦截到 Joinpoint 之后所要做的事情就是通知。说白了,就是一段功能性的代码。

通知的类型

  • 前置通知

  • 后置通知

  • 异常通知

  • 最终通知

  • 环绕通知

    try{
         // 前置通知【开启事务】
    
         // 业务代码....
    
         // 后置通知【提交事务】
    
    }catch (Exception  e){
         // 异常通知 【回滚事务】
    }finally {
         // 最终通知 【释放资源】
    }
    
2.2.5.4、织入

​ 全英叫:Weaving。是指把增强应用到目标对象来创建新的代理对象的过程,是一个动作。

2.2.5.5、切面

​ 全英叫:Aspect。是切入点和通知/增强的结合。

2.2.5.6、引介【了解】

​ 全英叫:Introduction。引介是一种特殊的通知在不修改类代码的前提下, Introduction可以在运行期为类动态地添加一些方法或Field。


好书推荐

在这里插入图片描述

《快捷学习Spring》

对于Java开发人员来说,Spring是必须学习的框架。这个不可思议的开发工具支持从小型企业电子商务应用程序到企业级微服务的一切。掌握Spring是一个漫长的过程。迈出第一步很容易!从这里开始。
本书向Java开发人员介绍如何使用Spring框架构建应用程序。书中包含信息丰富的图表以及相关的例子,作者清晰生动的写作,能帮助读者轻松掌握所需的技能。本书阐述了如何规划、编写和测试应用程序。通过关注最重要的特性,本书为探索Spring丰富的生态系统提供了坚实的基础。

作者简介

Laurenţiu Spilcă是Endava的专职开发主管和培训师,他负责欧洲、美国和亚洲客户的金融市场项目开发。他有超过10年的开发经验。Laurenţiu相信,重要的不仅是交付高质量的软件,还要分享知识和帮助他人提升技能。这些信念驱使他去设计和讲授与Java技术相关的课程,并进行演示和参与研讨会。

购书链接:点此进入

在这里插入图片描述

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

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

相关文章

梯度下降小结

1.梯度下降法&#xff08;Batch Gradient Desent&#xff0c;BGD&#xff09;&#xff1a; 总体m个样本&#xff0c;损失函数&#xff1a; 计算损失函数梯度&#xff1a; 参数更新&#xff1a; 2.随机梯度下降法&#xff08;Stochastic Gradient Desent&#xff0c;SGD&#x…

GEE图表案例——不同区域各地类面积直方图分布图表(矢量面积叠加直方图图)

简介 在GEE中对不同区域面积统计的直方图绘制具体流程如下: 数据准备: 首先,需要准备用于面积统计的地理数据,可以是矢量数据,如行政边界、土地使用类型等。也可以是栅格数据,如分类结果、土地覆盖数据等。 区域划分: 根据需要统计的区域,将数据进行区域划分。可以使用…

微软卡内基梅隆大学:无外部干预,GPT4等大语言模型难以自主探索

目录 引言&#xff1a;LLMs在强化学习中的探索能力探究 研究背景&#xff1a;LLMs的在情境中学习能力及其重要性 实验设计&#xff1a;多臂老虎机环境中的LLMs探索行为 实验结果概览&#xff1a;LLMs在探索任务中的普遍失败 成功案例分析&#xff1a;Gpt-4在特定配置下的探…

基于Java+SpringBoot+Vue幼儿园管理系统(源码+文档+部署+讲解)

一.系统概述 随着信息时代的来临&#xff0c;过去的传统管理方式缺点逐渐暴露&#xff0c;对过去的传统管理方式的缺点进行分析&#xff0c;采取计算机方式构建幼儿园管理系统。本文通过课题背景、课题目的及意义相关技术&#xff0c;提出了一种教 学生信息、学生考勤、健康记录…

智慧粮仓监测系统解决方案

一、概述 粮食储备是每个国家战略物资中最为重要的一项储备&#xff1b;而随着现代化农业的快速发展以及国家经济发展的需要&#xff0c;我国粮食产量和储备量长期处于世界前列。传统的粮仓由于修建年代久远&#xff0c;可能存在着设施落后&#xff0c;实时监控不到位的现象&am…

谷粒商城实战(011 业务-异步多线程)

Java项目《谷粒商城》架构师级Java项目实战&#xff0c;对标阿里P6-P7&#xff0c;全网最强 总时长 104:45:00 共408P 此文章包含第193p-第p202的内容 介绍 继承Thread 继承Runnable接口 继承callable FutureTask继承的就是runnable 线程池 代表有10个线程来等待接收我们的…

高并发秒杀系统

六种手段&#xff1a; 1.页面静态化 商品秒杀页面做静态化处理&#xff0c;常规请求不会到服务端。 2.cdn内容分发 将前端资源缓存到cdn上&#xff0c;就近分发给不同区域的客户端&#xff1b; 秒杀开始后将新的js文件同步到cdn上&#xff1b; 前端加一个控制器&#xff…

看看《MATLAB科研绘图与学术图表绘制从入门到精通》示例:绘制山鸢尾萼片长度和萼片宽度的小提琴图

使用MATLAB绘制鸢尾花数据集&#xff08; fisheriris&#xff09;中山鸢尾&#xff08; Iris Setosa&#xff09;的萼片长度和 萼片宽度的小提琴图。这将帮助我们更好地了解山鸢尾的这两个特征的数据分布情况&#xff0c;包括它们的 中位数、四分位范围及密度估计。这种可视化工…

老杜spring6自己笔记

精讲 【Spring视频零基础入门到高级&#xff0c;spring全套视频教程详解】 https://www.bilibili.com/video/BV1Ft4y1g7Fb/?p12&share_sourcecopy_web&vd_source833390c85450e4ff7747a5f16c02cc1e 老杜spring6网盘资料&#xff1a; 链接&#xff1a;https://pan.bai…

cesium 添加动态波纹效果 圆形扩散效果 波纹材质

一、扩展材质 /*** 水波纹扩散材质* param {*} options* param {String} options.color 颜色* param {Number} options.duration 持续时间 毫秒* param {Number} options.count 波浪数量* param {Number} options.gradient 渐变曲率*/function CircleWaveMaterialProperty(opt…

CF938Div3(A-F)

A: 买n个酸奶&#xff0c;一次一瓶a元,一次买两瓶可以优惠价b元,也可以a元,问恰好买n瓶需要多少钱. void solve() {int n, a, b;cin >> n >> a >> b;int ans min(a * n, n / 2 * b n % 2 * a);cout << ans << endl; } B: 给你一个数组,问能…

pdfjs-4.0.379-dist直接打开viewer.html报错

下载了pdfjs-4.0.379-dist&#xff0c;但是直接打开viewer.html报错。解决方法&#xff1a;安装live Sever&#xff0c;并用live Server打开 打开浏览器截图 错误提示如下&#xff1a; Access to image at file:///D:/work/web-common/car-knowledge-base-web/static/pdfjs-4…

OJ 栓奶牛【C】【Python】【二分算法】

题目 算法思路 要求的距离在最近木桩与最远木桩相隔距离到零之间&#xff0c;所以是二分法 先取一个中间值&#xff0c;看按照这个中间值可以栓多少奶牛&#xff0c;再与输入奶牛数比较&#xff0c;如果大于等于&#xff0c;则增大距离&#xff0c;注意这里等于也是增大距离…

AcWing1262.鱼塘钓鱼

【题目链接】1262. 鱼塘钓鱼 - AcWing题库 输入样例&#xff1a; 5 10 14 20 16 9 2 4 6 5 3 3 5 4 4 14输出样例&#xff1a; 76 【代码及详细注释】 #include<bits/stdc.h> using namespace std; typedef long long ll; const int N110; int a[N],b[N],sp[N],d[N]…

Unity Pro 2019 for Mac:专业级游戏引擎,助力创意无限延伸!

Unity Pro 2019是一款功能强大的游戏开发引擎&#xff0c;其特点主要体现在以下几个方面&#xff1a; 强大的渲染技术&#xff1a;Unity Pro 2019采用了新的渲染技术&#xff0c;包括脚本化渲染流水线&#xff0c;能够轻松自定义渲染管线&#xff0c;通过C#代码和材料材质&…

Day36:LeedCode 435. 无重叠区间 763.划分字母区间 56. 合并区间 蓝桥杯 管道

435. 无重叠区间 给定一个区间的集合 intervals &#xff0c;其中 intervals[i] [starti, endi] 。返回 需要移除区间的最小数量&#xff0c;使剩余区间互不重叠 。 示例 1: 输入: intervals [[1,2],[2,3],[3,4],[1,3]] 输出: 1 解释: 移除 [1,3] 后&#xff0c;剩下的区间…

Python 编程 深入了解内存管理机制、深拷贝与浅拷贝

&#x1f349; CSDN 叶庭云&#xff1a;https://yetingyun.blog.csdn.net/ 一、对象和引用、内存管理机制 Python 中的一切都是对象&#xff0c;包括数字、字符串、列表和函数等。为了简化内存管理并提高效率&#xff0c;Python 采用了统一的对象模型。在这个模型中&#xff0c…

c++——sort()函数

一、代码和效果 #include<bits/stdc.h> using namespace std;int main() {int a[6]{1,45,2,5,456,7};sort(a,a6);for(int i0; i<6; i){cout<<a[i]<<" "<<endl;}return 0; } 二、sort函数解析 &#xff08;从小到大&#xff09; std::so…

【C++】lambda表达式

目录 一、lambda表达式1.1 C98中的例子1.2 lambda表达式语法1.3 函数对象与lambda表达式 一、lambda表达式 1.1 C98中的例子 如果要对一个数据集合进行排序&#xff0c;可以使用sort函数&#xff1a; int main() {int array[] { 4,1,8,5,3,7,0,9,2,6 };// 默认按照小于比较…

15.leetcode---逆波兰表达式求值(Java版)

题目链接: https://leetcode.cn/problems/8Zf90G/description/ 题解: 栈 代码: 测试