Spring AOP高级应用与源码剖析

 更新时间:2025年12月12日 09:56:37   作者:guslegend  
Spring AOP通过动态代理,在不修改原有业务逻辑的情况下增强横切逻辑,如权限校验、日志记录、事务控制和性能监测,本文介绍Spring AOP高级应用与源码剖析,感兴趣的朋友跟随小编一起看看吧

Spring AOP 高级应用

AOP的本质:在不改变原有业务逻辑的情况下增强横切逻辑,横切逻辑代码往往是权限校验代码,日志代码,事务控制代码,性能监测代码。

AOP相关术语

名词

解释

JoinPoint(连接点)

可以用于把增强代码加入到业务主线中的点

Pointcut(切入点)

已经把增强代码加入到业务主线进来之后的连接点

Adice(通知/增强)

切面类中用于提供增强功能的方法

Target(目标对象)

代理的目标对象。即被代理对象

Proxy(代理)

一个类被AOP植入增强后,产生的代理类

Weaving(织入)

把增强应用到目标对象来创建新的代理对象的过程

Aspect(切面)

指定增强的代码所关注的方面,把这些相关的增强代码定义到一个类中,这个类就是切面类。

Spring中AOP的代理选择

AOP思想使用的是动态代理。默认情况下Spring会根据代理对象是否实现接口来选择使用JDK还是CGLIB。当代理对象没有实现任何接口时,Spring会选择CGLIB。

Spring中AOP实现XML形式

maven坐标

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aop</artifactId>
            <version>5.1.12.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.9.4</version>
        </dependency>

Aop核心配置

<!--
 Spring基于XML的AOP配置前期准备:
 在spring的配置⽂件中加⼊aop的约束
 xmlns:aop="http://www.springframework.org/schema/aop"
 http://www.springframework.org/schema/aop 
https://www.springframework.org/schema/aop/spring-aop.xsd 
 Spring基于XML的AOP配置步骤、
 第⼀步:把通知Bean交给Spring管理
 第⼆步:使⽤aop:config开始aop的配置
 第三步:使⽤aop:aspect配置切⾯
 第四步:使⽤对应的标签配置通知的类型
 ⼊⻔案例采⽤前置通知,标签为aop:before
-->
<!--把通知bean交给spring来管理-->
<bean id="logUtil" class="com.lagou.utils.LogUtil"></bean>
<!--开始aop的配置-->
<aop:config>
<!--配置切⾯-->
 <aop:aspect id="logAdvice" ref="logUtil">
 <!--配置前置通知-->
 <aop:before method="printLog" pointcut="execution(public *
com.lagou.service.impl.TransferServiceImpl.updateAccountByCardNo(com.lagou
.pojo.Account))"></aop:before>
 </aop:aspect>
</aop:config>

切入表达式,也称之为Aspectj切入点表达式,指的是遵循特定语法结构的字符串,其作用是用于对符合语法格式的连接点进行增强。

改变代理方式的配置:

我们知道只要不是final修饰的类都可以是cglib提供的方式来创建代理对象,spring提供了两种配置方式:

  • 使用aop:config标签配置
<aop:config proxy-target-class="true">
  • 使用aop:aspectj-autoproxy标签配置
<!--此标签是基于XML和注解组合配置AOP时的必备标签,表示Spring开启注解配置AOP的⽀持-->
<aop:aspectj-autoproxy proxy-target-class="true"></aop:aspectjautoproxy>

5中AOP通知类型:

1. 前置通知

  • 配置方式:<aop:before method="方法名" pointcut-ref="切入点引用"/>
  • 出现位置:仅在<aop:aspect>标签内
  • 执行时机:切入方法(业务核心方法)执行之前(必定执行)
  • 细节:可获取切入方法的参数并增强

2. 正常执行时通知(后置返回通知)

  • 配置方式:<aop:after-returning method="方法名" pointcut-ref="切入点引用"/>
  • 出现位置:仅在<aop:aspect>标签内
  • 执行时机:切入方法正常执行完成后(若方法抛异常则不执行)

3. 异常通知

  • 配置方式:<aop:after-throwing method="方法名" pointcut-ref="切入点引用"/>
  • 出现位置:仅在<aop:aspect>标签内
  • 执行时机:切入方法产生异常之后(无异常则不执行)
  • 细节:可获取切入方法的参数 + 异常信息

4. 最终通知

  • 配置方式:<aop:after method="方法名" pointcut-ref="切入点引用"/>
  • 出现位置:仅在<aop:aspect>标签内
  • 执行时机:切入方法执行完成后、返回之前(无论是否抛异常,必定执行)
  • 细节:可获取参数,常用于清理操作

5. 环绕通知

  • 配置方式:<aop:around method="方法名" pointcut-ref="切入点引用"/>
  • 出现位置:仅在<aop:aspect>标签内
  • 特殊说明:是 Spring 的 “特殊通知”,可通过编程控制通知执行时机(区别于前四种 “指定时机” 的通知);依赖ProceedingJoinPoint接口,实现手动触发切入方法的调用

Spring中AOP实现XML+注解形式

XML配置

注解配置

<aop:before method="方法名" pointcut-ref="切入点引用"/>

@Before

<aop:after-returning method="方法名" pointcut-ref="切入点引用"/>

@AfterReturning

<aop:after-throwing method="方法名" pointcut-ref="切入点引用"/>

@AfterThrowing

<aop:after method="方法名" pointcut-ref="切入点引用"/>

@After

<aop:around method="方法名" pointcut-ref="切入点引用"/>

@Around

Spring中AOP实现注解形式

在我们使用注解开发时候要用注解替换掉配置文件

<!--开启spring对注解aop的⽀持-->
<aop:aspectj-autoproxy/>

需要在启动类上面添加

@EnableAspectJAutoProxy //开启spring对注解AOP的⽀持

Spring声明式事务的支持

编程式事务:在业务代码中添加事务控制代码,这样的事务控制机制叫做编程式事务。

声明式事务:通过xml或者注解配置的方式达到事务控制的目的,叫做声明式事务。

事务的四大特性:

  1. 原子性:原子性式指事务是一个不可分割的工作单位,事务中的操作要么全部发生,要么全部不发生。
  2. 一致性:事务必须使数据库从一个一致性状态变换成另一个一致性状态。
  3. 隔离性:事务的隔离性式多个用户并发访问数据库时,数据库未每一个用户开启的事务,每个事务不能被其他事务的操作数据所干扰,多个并发事务之间要相互隔离。
  4. 持久性:持久性时指一个事务一旦被提交,它对数据中数据的改变就是永久性的,接下来即使数据库发送故障也不应该对其有任何影响。

不考虑事务隔离级别会出现的问题:

  1. 脏读:一个线程中的事务读到另一个线程中未提交的数据。
  2. 不可重复读:一个线程的事务读到另一个线程中已经提交的update的数据(前后内容不一样)。
  3. 幻读:一个线程中的事务读取到了另一个线程中已经提交的insert或者delete的数据(前后条数不一样)。

数据库中定义的四种隔离级别(从高到低):

  1. Serializable(串行化):避免脏读,不可重复读,虚读情况的发生。
  2. Repeatable read(可重复读):可避免脏读,不可重复读情况发生。
  3. Read committed(读已提交):可避免脏读情况发生。
  4. Read uncommitted(读未提交):以上情况都没有保证。

Mysql默认的事务隔离级别是:读已提交。
查询当前使用的隔离级别:SELECT @@session.transaction_isolation;

设置Mysql事务的隔离级别:(仅仅是当前会话的隔离级别)SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;

传播行为常量

中文名称

核心规则

适用场景

REQUIRED

(默认)

必需的

如果当前有事务,加入该事务;如果无事务,新建事务。

绝大多数业务(如订单 + 库存)

SUPPORTS

支持的

如果当前有事务,加入;无事务,则以非事务方式执行。

查询类方法(可选事务)

MANDATORY

强制的

必须在已有事务中执行;无事务则抛异常(IllegalTransactionStateException)。

核心子操作(必须依赖外层事务)

REQUIRES_NEW

新建的

无论当前是否有事务,都新建独立事务;原有事务暂停,新事务执行完后恢复。

日志记录、消息发送(独立事务)

NOT_SUPPORTED

不支持的

以非事务方式执行;若当前有事务,暂停原有事务。

纯查询(无需事务,提升性能)

NEVER

从不

必须以非事务方式执行;若当前有事务,抛异常。

绝对禁止事务的操作

NESTED

嵌套的

基于当前事务创建嵌套子事务(Savepoint 实现);子事务回滚不影响外层,外层回滚则全滚。

批量操作(部分失败可回滚)

纯xml方式

<!-- 配置事务管理器(基于JDBC数据源) -->
<bean id="transactionManager" 
      class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="dataSource" ref="dataSource"/> <!-- 引用已配置的数据源 -->
</bean>
<tx:advice id="txAdvice" transaction-manager="transactionManager">
    <tx:attributes>
        <!-- 全局默认配置:所有方法默认非只读,传播行为REQUIRED -->
        <tx:method name="*" read-only="false" 
                   propagation="REQUIRED" isolation="DEFAULT" timeout="-1"/>
        <!-- 针对查询方法的单独配置:只读,传播行为SUPPORTS -->
        <tx:method name="query*" read-only="true" propagation="SUPPORTS"/>
    </tx:attributes>
</tx:advice>
<aop:config>
    <!-- 切入点:匹配TransferServiceImpl类的所有方法 -->
    <aop:advisor advice-ref="txAdvice" 
                 pointcut="execution(* com.lagou.edu.service.impl.TransferServiceImpl.*(..))"/>
</aop:config>

xml+注解方式

<!-- 开启Spring注解事务的支持 -->
<tx:annotation-driven transaction-manager="transactionManager"/>
@Transactional(readOnly = true,propagation = Propagation.SUPPORTS)

纯注解方式

需要在启动类上加入@EnableTransactionManagement

到此这篇关于Spring AOP高级应用与源码剖析的文章就介绍到这了,更多相关Spring AOP源码分析内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Java Socket编程简介_动力节点Java学院整理

    Java Socket编程简介_动力节点Java学院整理

    这篇文章主要介绍了Java Socket编程简介的相关知识,非常不错,具有参考借鉴价值,需要的朋友可以参考下
    2017-05-05
  • SpringBoot实现Md5对数据库数据加密的示例

    SpringBoot实现Md5对数据库数据加密的示例

    本文主要介绍了SpringBoot实现Md5对数据库数据加密的示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-04-04
  • 如何通过Java生成一个随机数

    如何通过Java生成一个随机数

    当我们需要在Java中生成随机数时,可以借助JDK中提供的Random类来实现,通过使用Random类,我们可以轻松地生成各种类型的随机数,下面我们就来看看如何利用Random类生成随机数吧
    2023-09-09
  • Java通过反射查看类的信息示例

    Java通过反射查看类的信息示例

    这篇文章主要介绍了Java通过反射查看类的信息,结合实例形式详细分析了java基于反射获取类信息的相关原理与实现技巧,需要的朋友可以参考下
    2019-07-07
  • 如何在Spring data中使用r2dbc详解

    如何在Spring data中使用r2dbc详解

    这篇文章主要给大家介绍了关于如何在Spring data中使用r2dbc的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-11-11
  • Java利用遗传算法求解最短路径问题

    Java利用遗传算法求解最短路径问题

    遗传算法(Genetic Algorithm,GA)最早是由美国的John holland于20世纪70年代提出,该算法是根据大自然中生物体进化规律而设计提出的。本文将利用遗传算法求解最短路径问题,需要的可以参考一下
    2022-06-06
  • SpringBoot整合Security权限控制登录首页

    SpringBoot整合Security权限控制登录首页

    这篇文章主要为大家介绍了SpringBoot整合Security权限控制登录首页示例,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-11-11
  • maven工程中jar包瘦身的五种方法

    maven工程中jar包瘦身的五种方法

    这篇文章主要介绍了maven工程中jar包瘦身的五种方法,帮助大家更好的理解和使用maven,感兴趣的朋友可以了解下
    2021-02-02
  • SpringCloud中Gateway的使用教程详解

    SpringCloud中Gateway的使用教程详解

    SpringCloud Gateway是Spring体系内的一个全新项目,它旨在为微服务架构提供一种简单有效的统一的API路由管理方式。本文就来为大家详细讲讲Gateway的使用教程,需要的可以参考一下
    2022-08-08
  • 使用Spring事件监听机制实现跨模块调用的步骤详解

    使用Spring事件监听机制实现跨模块调用的步骤详解

    Spring 事件监听机制是 Spring 框架中用于在应用程序的不同组件之间进行通信的一种机制,Spring 事件监听机制基于观察者设计模式,使得应用程序的各个部分可以解耦,提高模块化和可维护性,本文给大家介绍了使用Spring事件监听机制实现跨模块调用,需要的朋友可以参考下
    2024-06-06

最新评论