【Spring】Spring的AspectJ的AOP

news2025/1/12 8:48:54

Spring学习笔记(10)Spring的AspectJ的AOP

在Spring中使用AspectJ实现AOP

  • AspectJ 是一个面向切面的框架, 它扩展了 Java 语言。 AspectJ 定义了 AOP 语法所以它有一个专门的编译器用来生成遵守 Java 字节编码规范的 Class 文件。
  • AspectJ 是一个基于 Java 语言的 AOP 框架
  • Spring2.0 以后新增了对 AspectJ 切点表达式支持
  • @AspectJ 是 AspectJ1.5 新增功能, 通过 JDK5 注解技术, 允许直接在 Bean 类中定义切面
  • 新版本 Spring 框架, 建议使用 AspectJ 方式来开发 AOP

AspectJ 表达式

那些类允许增强的表达式

语法:execution(表达式)
execution(<访问修饰符>?<返回类型><方法名>(<参数>)<异常>)
[*代表方法的返回值为任意类型] [*代表所有方法] [..代表任意参数类型]

  • execution(* cn.itcast.spring3.demo1.dao.*(..)) —只检索当前包

  • execution(* cn.itcast.spring3.demo1.dao..*(..)) —检索包及当前包的子包.

  • execution(* cn.itcast.dao.GenericDAO+.*(..)) —检索 GenericDAO 及子类

  • 匹配所有类 public 方法 execution(public * *(..))

  • 匹配指定包下所有类方法 execution(* cn.itcast.dao.*(..)) 不包含子包

  • execution(* cn.itcast.dao..*(..)) ..*表示包、 子孙包下所有类

  • 匹配指定类所有方法 execution(*cn.itcast.service.UserService.*(..))

  • 匹配实现特定接口所有类方法execution(*cn.itcast.dao.GenericDAO+.*(..))

  • 匹配所有 save 开头的方法 execution(* save*(..))

AspectJ 增强

@Before 前置通知, 相当于 BeforeAdvice
@AfterReturning 后置通知, 相当于 AfterReturningAdvice
@Around 环绕通知, 相当于 MethodInterceptor
@AfterThrowing 抛出通知, 相当于 ThrowAdvice
@After 最终 final 通知, 不管是否异常, 该通知都会执行
@DeclareParents 引介通知, 相当于 IntroductionInterceptor

基于注解

1.引入jar包

  • pom.xml
<dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.12</version>
      <scope>test</scope>
    </dependency>

    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-context</artifactId>
      <version>${spring.version}</version>
    </dependency>

    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-test</artifactId>
      <version>${spring.version}</version>
    </dependency>
    <!--解析切入点表达式-->
    <dependency>
      <groupId>org.aspectj</groupId>
      <artifactId>aspectjweaver</artifactId>
      <version>1.9.4</version>
    </dependency>

2.编写增强的类

  • UserDao
@Repository(value = "userDao") //注解的方式,spring管理对象的创建
public class UserDao {
    public void add(){
        System.out.println("添加用户");
    }
    public void addInfo(){
        System.out.println("添加用户信息");
    }
    public void update(){
        System.out.println("更新用户");
    }
    public void delete(){
        System.out.println("删除用户");
    }
    public void find(){
        System.out.println("查找用户");
    }
}

3.使用AspectJ注解形式

  • MyAspectJ
@Component // 注解的方式,spring管理对象的创建
@Aspect  // 用来定义且切面
public class MyAspectJ {
    /**
     * 前置通知
     * 对UserDao里面的以add方法进行增强
     * @param joinPoint
     */
    @Before("execution(* club.krislin.Dao.UserDao.add*(..))")
    public void before(JoinPoint joinPoint){
        //打印的是切点信息
        System.out.println(joinPoint);
        System.out.println("前置增强");
    }

    /**
     * 后置通知
     * 对update开头的方法进行增强
     * @param returnValue
     */
    @AfterReturning(value = "execution(* club.krislin.Dao.UserDao.update*(..))",returning = "returnValue") // 接受返回值,方法的返回值为任意类型
    public void after(Object returnValue){
        System.out.println("后置通知");
        System.out.println("方法的返回值为:"+returnValue);
    }

    /**
     * 环绕通知增强
     * 对以find开头的方法进行增强
     * @param proceedingJoinPoint
     * @return
     * @throws Throwable
     */
    @Around(value = "execution(* club.krislin.Dao.UserDao.find*(..))")
    public Object arount(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        System.out.println("环绕通知增强-----前");
        // 执行目标方法
        Object obj = proceedingJoinPoint.proceed();
        System.out.println("环绕通知增强-----后");
        return obj;
    }

    /**
     * 异常通知增强
     * 对以find开头的方法进行增强
     * @param e
     */
    @AfterThrowing(value = "execution(* club.krislin.Dao.UserDao.find(..))",throwing = "e")
    public void afterThrowing(Throwable e){
        System.out.println("出现异常"+e.getMessage());
    }

    @After(value = "execution(* club.krislin.Dao.UserDao.find(..))")
    public void after(){
        System.out.println("最终通知");
    }
}

4.配置applicationContext.xml

<!--自动生成代理底层就是 AnnotationAwareAspectJAutoProxyCreator-->
    <aop:aspectj-autoproxy></aop:aspectj-autoproxy>

    <context:component-scan base-package="club.krislin"></context:component-scan>

5.测试

  • UserDaoTest
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:applicationContext.xml")
public class UserDaoTest {
    @Resource(name = "userDao")
    private UserDao userDao;

    @Test
    public void testUserDao(){
        userDao.add();
        userDao.addInfo();
        userDao.delete();
        userDao.find();
        userDao.update();
    }
}

基于xml

1.编写被增强的类

  • UserDao
public class UserDao {
    public void add(){
        System.out.println("添加用户");
    }
    public void addInfo(){
        System.out.println("添加用户信息");
    }
    public void update(){
        System.out.println("更新用户");
    }
    public void delete(){
        System.out.println("删除用户");
    }
    public void find(){
        System.out.println("查找用户");
        //int i = 1;
        //int n = i/0;
    }
}

2.编写增强的类

  • MyAspectJ
public class MyAspectJ {
    /**
     * 前置通知
     * @param joinPoint
     */
    public void before(JoinPoint joinPoint){
        //打印的是切点信息
        System.out.println(joinPoint);
        System.out.println("前置增强");
    }

    /**
     * 后置通知
     * @param returnValue
     */
       public void after(Object returnValue){
        System.out.println("后置通知");
        System.out.println("方法的返回值为:"+returnValue);
    }

    /**
     * 环绕通知增强
     * @param proceedingJoinPoint
     * @return
     * @throws Throwable
     */
    public Object arount(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        System.out.println("环绕通知增强-----前");
        // 执行目标方法
        Object obj = proceedingJoinPoint.proceed();
        System.out.println("环绕通知增强-----后");
        return obj;
    }

    /**
     * 异常通知增强
     * @param e
     */
    public void afterThrowing(Throwable e){
        System.out.println("出现异常"+e.getMessage());
    }

    /**
     * 最终通知增强
     */
    public void after(){
        System.out.println("最终通知");
    }
}

3配置applicationContext.xml

<!--定义被增强的类-->
    <bean name="userDao" class="club.krislin.Dao.UserDao"></bean>
    <!--定义切面类-->
    <bean name="myAspectJ" class="club.krislin.MyAspectJ"></bean>

    <!--定义aop配置-->
    <aop:config>
        <!--定义哪些方法上使用增强-->
        <aop:pointcut expression="execution(* club.krislin.Dao.UserDao.add*(..))" id="myPointcut"/>

        <aop:pointcut expression="execution(* club.krislin.Dao.UserDao.add(..))" id="myPointcut1"/>

        <aop:aspect ref="myAspectJ">
            <!--在add开头的方法上采用前置通知-->
            <aop:before method="before" pointcut-ref="myPointcut"/>
        </aop:aspect>
        <aop:aspect ref="myAspectJ">
            <!--后置通知-->
            <aop:after-returning method="after" pointcut-ref="myPointcut" returning="returnValue"/>
        </aop:aspect>
        <aop:aspect ref="myAspectJ">
            <!--环绕通知-->
            <aop:around method="arount" pointcut-ref="myPointcut"/>
        </aop:aspect>
        <aop:aspect ref="myAspectJ">
            <!--异常通知-->
            <aop:after-throwing method="afterThrowing" pointcut-ref="myPointcut" throwing="e"/>
        </aop:aspect>
        <aop:aspect ref="myAspectJ">
            <!--最终通知-->
            <aop:after method="after" pointcut-ref="myPointcut1"/>
        </aop:aspect>
    </aop:config>

4.测试

  • UsetDaoTest
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:applicationContext.xml")
public class UserDaoTest {
    @Resource(name = "userDao")
    private UserDao userDao;

    @Test
    public void testUserDao(){
        userDao.add();
        userDao.addInfo();
        userDao.delete();
        userDao.update();
        userDao.find();
    }
}

xml方式的AOP配置步骤

1.配置被增强的类和通知(即增强方法)

2.使用aop:config声明aop配置

aop:config 用于声明开始aop的配置

<aop:config>
    <!-- 配置的代码都写在此处 -->
</aop:config>

3.使用aop:aspect配置切面

aop:aspect 用于配置切面
属性: id:给切面提供一个唯一的表示
ref:引用配置好的通知类bean的id

<aop:aspect id="txAdvice" ref="txManager">
    <!--配置通知的类型要写在此处-->
</aop:aspect>

4.使用aop:pointcut配置切入点表达式

aop:pointcut 用于配置切入点表达式.就是指定对哪些类的哪些方法进行增强
属性: expression:由于定义切入表达式
id:用于给切入点表达式提供唯一的标识

<aop:pointcut expression="execution(* club.krislin.Dao.UserDao.add*(..))" id="myPointcut"/>

5.使用aop:xxx配置对应的通知类型

aop:before 用于配置前置通知.指定增强的方法在切入点方法之前执行
属性: method:用于指定通知类中的增强方法名称
pointcut-ref:用于指定切入点表达式的引用
pointcut:用于指定切入点表达式
执行时间: 切入点方法执行之前

<aop:before method="before" pointcut-ref="myPointcut"/>

aop:after-returning 用于配置后置通知
属性: method:用于指定通知类中的增强方法名称
pointcut-ref:用于指定切入点表达式的引用
pointcut:用于指定切入点表达式
returning:后置通知返回值
执行时间:切入点方法正常执行之后,它和异常通知只能有一个执行

 <aop:after-returning method="after" pointcut-ref="myPointcut" returning="returnValue"/>

aop:after-throwing 用于配置异常通知
属性: method:用于指定通知类中的增强方法名称
pointcut-ref:用于指定切入点表达式的引用
pointcut:用于指定切入点表达式
throwing:指定抛出的异常
执行时间:切入点方法执行异常后执行,它和后置通知只能有一个执行

<aop:after-throwing method="afterThrowing" pointcut-ref="myPointcut" throwing="e"/>

aop:after: 用于配置最终通知
属性: method:用于指定通知类中的增强方法名称
pointcut-ref:用于指定切入点表达式的引用
pointcut:用于指定切入点表达式
执行时间:无论切入点方法执行时是否异常,它都会在后面执行

<aop:after method="after" pointcut-ref="myPointcut1"/>

aop:around 用于配置环绕通知
属性: method:用于指定通知类中的增强方法名称
pointcut-ref:用于指定切入点表达式的引用
pointcut:用于指定切入点表达式

<aop:around method="arount" pointcut-ref="myPointcut"/>

Advisor 和 Aspect 的区别?(都叫切面)

  • Advisor:Spring 传统意义上的切面:支持一个切点和一个通知的组合.
  • Aspect:可以支持多个切点和多个通知的组合.

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

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

相关文章

[附源码]java毕业设计双学位在线考试系统

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

01-mysql基础

MySQL基础 今日目标&#xff1a; 完成MySQL的安装及登陆基本操作能通过SQL对数据库进行CRUD能通过SQL对表进行CRUD能通过SQL对数据进行CRUD 1&#xff0c;数据库相关概念 以前我们做系统&#xff0c;数据持久化的存储采用的是文件存储。存储到文件中可以达到系统关闭数据不会…

[附源码]SSM计算机毕业设计远程教育系统JAVA

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

Springboot项目集成Swagger3.0

目录一&#xff0c;Swagger简介二&#xff0c;集成Swagger1&#xff0c;引依赖2&#xff0c;写配置3&#xff0c;配置说明3.1&#xff0c;暴露接口3.2&#xff0c;补充信息4&#xff0c;加注解注解说明三&#xff0c;测试一&#xff0c;Swagger简介 开发时经常会出现下面这种情…

【Redis从入门到进阶】第 1 讲:Redis的五大基本数据类型

本文已收录于专栏&#x1f345;《Redis从入门到进阶》&#x1f345;专栏前言 本专栏开启&#xff0c;目的在于帮助大家更好的掌握学习Redis&#xff0c;同时也是为了记录我自己学习Redis的过程&#xff0c;将会从基础的数据类型开始记录&#xff0c;直到一些更多的应用&#xf…

《十八》JS 中的错误处理

error 对象&#xff1a; error 对象是当错误发生时提供错误信息的 JS 内置对象。 当错误发生时&#xff0c;浏览器会生成 error 对象并抛出&#xff0c;并且中断后面代码的执行。 console.log(person.name) console.log(不会被执行到)也可以通过 Error() 构造函数自定义 err…

使用Resnet网络对人脸图像分类识别出男女性别(包含数据集制作+训练+测试)

文章目录前言一、数据预处理1.分类数据存放2.生成train.txt与val.txt二、更改配置文件1.自定义修改三、定义resnet网络四、train.py训练五、预测predict.py实现六、预测结果七、完整项目代码数据集(大于1500张)总结前言 本打算昨天写这篇博客的&#xff0c;推迟到今天晚上。实…

章节3 配置CentOS

3.1-什么是虚拟机 什么是虚拟机&#xff1f; Virtual Machine&#xff0c;虚拟软件/平台虚拟出来的操作系统。 虚拟机/物理机 虚拟化技术 虚拟化软件&#xff1a;VMware Workstation、VirtualBox、Virtual PC、Citrix Xen Desktop、Parallels Desktop&#xff08;MacOS&am…

刷题日记【第十五篇】-笔试必刷题【有假币+求正数数组的最小不可组成和+最难的问题+因子个数】

1.实例方法需要通过super来调用超类中的实例方法&#xff1b;实例方法需要通过类名称来调用超类的类方法&#xff1b;实例方法需要向下转型才能调用子类的实例方法&#xff1b;实例方法可以直接调用本类的实例方法。 2.HashSet子类依靠【hashCode();equals()】方法区分重复元素…

2.6 场效应管放大电路

一、场效应管放大电路的三种接法 场效应管的源极、栅极和漏极与晶体管的发射极、基极和集电极相对应&#xff0c;因此在组成放大电路时也有三种接法&#xff0c;即共源放大电路、共漏放大电路和共栅放大电路。以 NNN 沟道结型场效应管为例&#xff0c;三种接法的交流通路如图2…

Python 3.11 有什么新功能?

详细概述Python 3.11中最重要功能&#xff0c;包括如何安装 beta 版本以及何时可以获得官方稳定版本。 长按关注《Python学研大本营》&#xff0c;加入读者群&#xff0c;分享更多精彩 扫码关注《Python学研大本营》&#xff0c;加入读者群&#xff0c;分享更多精彩 Python在过…

【毕业设计】24-基于单片机的电子显示屏的设计与应用(原理图+源码+仿真工程+论文+答辩PPT)

【毕业设计】24-基于单片机的电子显示屏的设计与应用&#xff08;原理图源码仿真工程论文答辩PPT&#xff09; 文章目录资料下载链接任务书设计说明书摘要设计框架架构设计说明书及设计文件源码展示资料下载链接 资料下载链接 资料链接&#xff1a;https://www.cirmall.com/ci…

SpringBoot SpringBoot 开发实用篇 4 数据层解决方案 4.13 ES 下载与安装

SpringBoot 【黑马程序员SpringBoot2全套视频教程&#xff0c;springboot零基础到项目实战&#xff08;spring boot2完整版&#xff09;】 SpringBoot 开发实用篇 文章目录SpringBootSpringBoot 开发实用篇4 数据层解决方案4.13 ES 下载与安装4.13.1 下载4.13.2 安装4.13.3 使…

网页设计作业学生网页课程设计作业成品DIV+CSS-关于家乡的HTML网页设计

Web前端开发技术 描述 网页设计题材&#xff0c;DIVCSS 布局制作,HTMLCSS网页设计期末课程大作业&#xff0c;游景点介绍 | 旅游风景区 | 家乡介绍 | 等网站的设计与制作 | HTML期末大学生网页设计作业 HTML&#xff1a;结构 CSS&#xff1a;样式 在操作方面上运用了html5和cs…

卷积神经网络总结

卷积操作特征图大小计算 图中蓝色部分为55大小的输入卷积层的特征图&#xff0c;黄色部分 为33大小的卷积核&#xff0c;其内部黑色数字为卷积核权重参数&#xff0c;经过卷积操作以后得 到右侧绿色33大小的输出特征图。 如果使用input_N表示输入图像的大小&#xff0c;n表示参…

DJYOS驱动开发系列二:基于DJYOS的IIC驱动编写指导手册

1.概述 DJYOS的DjyBus总线模型为IIC、SPI之类的器件提供统一的访问接口&#xff0c;IICBUS模块是DjyBus模块的一个子模块&#xff0c;为IIC器件提供统一的编程接口&#xff0c;实现通信协议层与器件层的分离。也标准化了IIC总线和 Device驱动接口&#xff0c;本手册指导驱动工…

树与二叉树(二)

**&#x1f6c0; ♡ ♢ ♤ ♧ ♣ ♦ ♥ ♠&#x1f6c0;** &#x1f4a5;**欢迎来到半之半的博客**&#xff0c;**这篇文章主要讲述数据结构中非常重要的一块内容&#xff0c; 即树与二叉树&#xff0c;相信大家学完必会加深自己的理解。&#x1f4a5;****&#x1f55d;我是半只…

Android BLE HIDS Data ,从问询DB 到写入Android 节点的flow 之三

问题点5&#xff1a;Android BLE具体连接flow 并问询DB的API flow 之第二阶段问询&#xff1b; 表示第二阶段的log “Start service discovery: srvc_idx ”在Android9没有&#xff0c;但在Android 8.0中有&#xff0c;所以后续截图基于Android8.0。 -->执行API bta_gattc_…

ORB-SLAM2 ---- Initializer::ReconstructH函数

目录 1.函数作用 2.函数解析 2.1 调用函数解析 2.2 Initializer::ReconstructH函数总体思路 2.2.1 代码 2.2.2 总体思路解析 3.Initializer::CheckRT 3.1 函数作用 3.2 构造函数 3.3 代码 3.4 流程解析 3.4.0 初始化参数 3.4.1 计算初始化两帧的投影矩阵 3.…

[计算机毕业设计]基于SM9的密钥交换方案的实现与应用

前言 &#x1f4c5;大四是整个大学期间最忙碌的时光,一边要忙着准备考研,考公,考教资或者实习为毕业后面临的就业升学做准备,一边要为毕业设计耗费大量精力。近几年各个学校要求的毕设项目越来越难,有不少课题是研究生级别难度的,对本科同学来说是充满挑战。为帮助大家顺利通过…