【Spring】通过Aspects实现面向切面编程(AOP)

news2024/11/24 12:25:01

目录

1.概念理解

2. 案例说明


1.概念理解

【注】一些概念来自:https://blog.csdn.net/Kaiser__/article/details/135894150

  1. 横切关注点

    分散在每个各个模块中解决同一样的问题,如用户验证、日志管理、事务处理、数据缓存都属于横切关注点。这个概念不是语法层面的,而是根据附加功能的逻辑上的需要:有十个附加功能,就有十个横切关注点。

  2. 通知(增强)
    增强,通俗说,就是你想要增强的功能,比如 安全,事务,日志等。

    每一个横切关注点上要做的事情都需要写一个方法来实现,这样的方法就叫通知方法。

    前置通知:在被代理的目标方法前执行
    返回通知:在被代理的目标方法成功结束后执行
    异常通知:在被代理的目标方法异常结束后执行
    后置通知:在被代理的目标方法最终结束后执行
    环绕通知:使用try…catch…finally结构围绕整个被代理的目标方法,包括上面四种通知对应的所有位置

  3. 切面
    封装通知方法的类。

  4. 目标
    被代理的目标对象。

  5. 代理
    向目标对象应用通知之后创建的代理对象。

  6. 连接点
    通俗说,就是spring允许使用通知的地方

  7. 切入点
    定位连接点的方式。每个类的方法中都包含多个连接点,所以连接点是类中客观存在的事物(从逻辑上来说)。如果把连接点看作数据库中的记录,那么切入点就是查询记录的 SQL 语句。

                            

AspectJ实施增强的类需要配置为切面,AspectJ提供了下列注解用于配置切面,注解如下:

  • @Aspect 配置一个类为切面类
  • @Before 配置一个方法为前置增强
  • @After 配置一个方法为后置增强
  • @AfterReturning 配置一个方法为返回后增强
  • @AfterThrowing 配置一个方法为抛出异常后增强
  • @Around 配置一个方法为环绕增强
  • @DeclareParents 配置一个属性为引介增强(类级别)

切入点表达式

  • execution(权限修饰符 方法返回值 方法所在类的全类名 方法名(参数列表))
  • 如果我们想覆盖test类中的所有方法,那么切入点表达式如下所示:

        execution(* com.its.spring.test.*(…))

        解释:

        第一个*代表对方法权限和返回类型不限
        com.its.spring.test是该方法的全类名
        第二个*代表任意方法名
        (…)代表任意参数

2. 案例说明

(1)环境准备

在项目的pom.xml文件中添加相关依赖

<!--实现AOP的依赖-->
    <dependency>
       <groupId>aspectj</groupId>
     <artifactId>aspectjrt</artifactId>
      <version>1.5.3</version>
    </dependency>
    <dependency>
      <groupId>aspectj</groupId>
       <artifactId>aspectjweaver</artifactId>
       <version>1.5.3</version>
    </dependency>
    <dependency>
       <groupId>aopalliance</groupId>
       <artifactId>aopalliance</artifactId>
      <version>1.0</version>
    </dependency>

在配置文件中开启AOP编程

 <!-- 配置AspectJ支持aop -->
    <aop:aspectj-autoproxy />

(2)代码实现

1.首先定义一个业务类AopService

package com.its.service;

import com.its.mapper.AopDao;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class AopService {
    @Autowired
    private AopDao aopDao;
    public void add(String name){
        System.out.println("增加"+name);
    }
    public void delete(String name){
        System.out.println("删除"+name);
    }
}

2.再定义一个切面类ServiceAopTest,用在业务类方法执行AOP编程

package com.its.aop;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;

@Aspect
@Component
public class ServiceAopTest {
    //    前置增强
    @Before("execution(* com.its.service.AopService.*(..))")
    public void ts02() {
        System.out.println("在所有方法前,增加的内容");
    }

    @Before("execution(* com.its.service.AopService.add(..))")
    public void ts01() {
        System.out.println("在add方法前,增加的内容");
    }

    @Before("execution(* com.its.service..*(..))")
    public void ts03() {
        System.out.println("在当前service包下的所有类的所有方法前执行");
    }

    //    后置增强
    @After("execution(* com.its.service..*(..))")
    public void ts04() {
        System.out.println("在当前service包下的所有类的所有方法后执行");
    }

    @After("execution(* com.its.service.AopService.*(..))")
    public void ts05() {
        System.out.println("在所有方法后,增加的内容");
    }

    @After("execution(* com.its.service.AopService.add(..))")
    public void ts06() {
        System.out.println("在add方法后,增加的内容");
    }

    // 返回后通知
    @AfterReturning("execution(* com.its.service.AopService.*(..))")
    public void returning() {
        System.out.println("返回后通知");
    }

    //环绕通知
    @Around("execution(* com.its.service..*(..))")
    public Object t05(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        System.out.println("=====1====="); //前置
        Object proceed = proceedingJoinPoint.proceed();
        System.out.println("=====2====="); //后置
        return proceed;
    }

    // 异常通知,方法发生异常时通知
    @AfterThrowing("execution(* com.its.service.AopService.*(..))")
    public void afterThrowing() {
        System.out.println("异常通知");
    }


}

注:该类需要使用 @Aspect 注解标识

3.执行测试代码

package com.its;

import com.its.service.AopService;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath:spring.xml"})
public class AopTest {
    @Autowired
    private AopService aopService;
    @Test
    public void test(){
        aopService.add("李明");
    }
    @Test
    public void test01(){
        aopService.delete("李海");
    }
}

4.结果如下

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

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

相关文章

【C++刷题】优选算法——贪心第一辑

什么是贪心算法 贪心策略&#xff1a;局部最优 -> 全局最优 “贪婪鼠目寸光” 1、把解决问题的过程分为若干步 2、解决每一步的时候&#xff0c;都选择当前看起来“最优的”解法 3、“希望”得到全局最优解 贪心算法的特点 贪心策略的提出是没有标准或者模板的 正确的贪心策…

项目小结(中)

一.文件分片上传 在文件上传的逻辑中&#xff0c;文件以MD5唯一&#xff0c;然后记录已经储存的文件md5&#xff0c;如果已上传&#xff0c;就秒传&#xff0c;并记录班级上传文件信息。 如果请求文件上传时&#xff0c;发现班级已经上传了一部分&#xff0c;这里就会把班级上…

秋招复习笔记——八股文部分:网络IP

终于来到了网络的最后一篇&#xff0c;继续加油&#xff01; IP 知识全家桶 IP 基本认识 IP 在 TCP/IP 参考模型中处于第三层&#xff0c;也就是网络层。 网络层的主要作用是&#xff1a;实现主机与主机之间的通信&#xff0c;也叫点对点&#xff08;end to end&#xff09…

【Vue3】Pinia修改数据

【Vue3】Pinia修改数据 背景简介开发环境开发步骤及源码总结 背景 随着年龄的增长&#xff0c;很多曾经烂熟于心的技术原理已被岁月摩擦得愈发模糊起来&#xff0c;技术出身的人总是很难放下一些执念&#xff0c;遂将这些知识整理成文&#xff0c;以纪念曾经努力学习奋斗的日子…

锐捷RCNA | 远程登录与路由技术

锐捷RCNA | 远程登录与路由技术 一、远程登录配置1. Telnet远程登录介绍2. 案例1--设置远程登录密码实现远程登录3. 案例2--定义不同用户账户实现远程用户权限隔离4. SSH远程登录介绍5. 案例--通过SSH功能远程管理设备 二、路由技术1. 直连路由的数据通信2. 间接路由的数据通信…

标准IO

fprintf和fscanf fprintf int printf(const char *format, ...); 把数据输出到终端 int fprintf(FILE *stream, const char *format, ...); 功能&#xff1a; 将format字符串中的内容&#xff0c;输出到stream文件流指针指向的文件中去&#xff0c;想要将数据以何种形式输…

基于XxlCrawler的Java执行JS渲染方式实战-以获取商飞C919飞行照片为例

目录 前言 一、抓取目标解析 1、原始网站介绍 2、列表页面结构解析 二、XxlCrawler的常规配置 1、PageVo对象的定义 2、定义XxlCrawler并启动 三、使用HtmlUnit来执行动态渲染 1、在pom.xml中加入htmlunit的引用 2、设置PageLoader加载器 3、执行抓取 四、总结 前言…

看,esp8266就是这么简单

材料准备 1.esp 8266 2.一条可以传输数据的数据线 3一台电脑 前言 如今是物联网的时代&#xff0c;例如“智能家居&#xff0c;无人驾驶……”&#xff0c;多方面的进行物联网改革与创新。那其中&#xff0c;物联网主要的是联网。那通常都是以“esp 8266”和“esp 32”占据了…

在Kylin服务器安装PostgreSQL16数据库

1、下载PostgreSQL16安装包 下载地址https://www.postgresql.org/ftp/source/v16.3/ 2、安装依赖和ICU库 查看服务器版本 yum install -y perl-ExtUtils-Embed readline-devel zlib-devel pam-devel libxml2-devel libxslt-devel openldap-devel python-devel gcc-c opens…

在抖音做电商推广,货架场非做不可

前一段时间跟几个做电商的朋友聊天&#xff0c;我发现大家的干劲儿还挺满的&#xff0c;讨论的话题也出奇地一致&#xff1a;要找新增量。 其中有个朋友是做服装品类的&#xff0c;做得还不错。我请教他秘诀&#xff0c;他说&#xff1a;做电商&#xff0c;推广拿量非常关键。…

MySQL笔记(七):索引

一、索引优化速度 创建对应字段的索引&#xff0c;只对该列有效&#xff0c;只能提高该列的查询速度 创建索引后&#xff0c;查询速度变快&#xff0c;但是表占用空间变大 create index 索引名 on 表名(需要创建索引的列)二、索引的原理 普通索引允许该字段重复 全文索引&#…

Resize Observer监测DOM元素尺寸改变的神器

前言 大家在遇到需要监测DOM元素尺寸大小的需求时&#xff0c;可能第一时间想到的都是使用window.addEventListener来监听resize 事件&#xff0c; 但是reize事件会在一秒内触发将近60次&#xff0c;所以很容易在改变窗口大小时导致性能问题。因为它会监听我们页面每个元素的…

MySQL总体功能

基于Innodb存储引擎的讨论 MySQL 核心功能 功能解决的问题ACID模型数据并发访问&#xff0c;和奔溃恢复安全问题,一致性&奔溃恢复索引数据查询效率问题备份容错设计,解决硬件错误带来的问题复制数据迁移监控执行数据库操作的异常记录

《嵌入式 - 嵌入式大杂烩》ARM Cortex-M寄存器详解

1 ARM Cortex-M寄存器概述 ARM Cortex-M提供了 16 个 32 位的通用寄存器(R0 - R15),如下图所示。前15个(R0 - R14)可以用作通用的数据存储,R15 是程序计数器 PC,用来保存将要执行的指令。除了通用寄存器,还有一些特殊功能寄存器。特殊功能寄存器有预定义的功能,而且必须通…

Java编码算法

编码 1.编码算法2.URL编码**URLEncoder类&#xff0c;主要进行编码****URLDecoder类&#xff0c;主要进行解码** 3.Base64编码Base64编码Base64的补充字符Base64的占位符Base64的应用 结论&#xff1a; 1.编码算法 什么是编码? ASCII码就是一种编码&#xff0c;字母A的编码是…

C语言典型例题28

《C程序设计教程&#xff08;第四版&#xff09;——谭浩强》 习题2.5 输入一个华氏温度&#xff0c;要求输出摄氏温度。公式为C5/9(F-32)&#xff0c;要求输出要有文字说明&#xff0c;取两位小数 数学知识&#xff1a; &#xff08;1&#xff09;华氏温度与摄氏温度&#x…

MySQL(六):mysql 约束

基本介绍&#xff1a;约束用于确保数据库的数据满足特定的商业规则&#xff0c;约束包括&#xff1a;not null、unique、primary key、foreign key 、check五种。 一、主键的使用&#xff08;primary key) 字段名 字段类型 primary key用于唯一的表示表行的数据&#xff0c;当…

SpringBoot基础 第二天

SpringBoot对静态资源的映射: (1) 要在src/main/resources文件夹下创建static和templates两个文件夹staitc存储静态资源,templates存储模板引擎 (2)要在pom.xml依赖下导入依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId>…

VS项目打包成lib库并使用

一、新建一个静态库项目 一般要把项目设为Release模式 二、添加文件 将所需要打包的头文件、源文件添加到该静态库项目中 三、生成项目 生成成功后即可在Release文件夹出现找到相应的.lib文件 四、使用静态库 将静态库文件复制到项目文件夹中&#xff0c;然后在项目属性设…

LSV实验——部署DR模式集群

目录 一、实验环境 二、配置 1、LVS 2、router 3、client 4、RS 三、配置策略 1.Director服务器采用双IP桥接网络&#xff0c;一个是VPP&#xff0c;一个DIP 2.Web服务器采用和DIP相同的网段和Director连接 3.每个Web服务器配置VIP 4.每个web服务器可以出外网 一、实验环…