Spring AOP及事务配置三种模式详解
Spring AOP简述
Spring AOP的设计思想,就是通过动态代理,在运行期对需要使用的业务逻辑方法进行增强。
使用场景如:日志打印、权限、事务控制等。
默认情况下,Spring会根据被代理的对象是否实现接口来选择使用JDK还是CGLIB。当被代理对象没有实现接口时,Spring会选择CGLIB。当实现了接口,Spring会选择JDK官方的代理技术,不过我们也可以通过配置的方式,让Spring强制使用CGLIB。
配置方式有两种:
- 使⽤aop:config标签配置
<aop:config proxy-target-class="true">
- 使⽤aop:aspectj-autoproxy标签配置
<aop:aspectj-autoproxy proxy-target-class="true"></aop:aspectj-
autoproxy>
Spring中AOP的实现
2.1 XML模式
- 引入依赖(如果项目里没有的话)
<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>
- xml配置
主要看下面的aop部分
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/tx
https://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/aop
https://www.springframework.org/schema/aop/spring-aop.xsd
">
xml相关切面配置
<bean id="logUtil" class="com.mmc.ioc.utils.LogUtil"></bean>
<!--aop的配置-->
<!--aop的配置-->
<aop:config>
<!--配置切面-->
<aop:aspect id="logAdvice" ref="logUtil">
<aop:pointcut id="logAspect" expression="execution(public * com.mmc.ioc.service.impl.TransferServiceImpl.transfer(..))"></aop:pointcut>
<!--前置通知-->
<aop:before method="printLog" pointcut-ref="logAspect"></aop:before>
<!--后置通知,无论业务是否正常执行-->
<aop:after method="after" pointcut-ref="logAspect"></aop:after>
<!--正常执行-->
<aop:after-returning method="afterReturn" pointcut-ref="logAspect"></aop:after-returning>
<!--异常执行-->
<aop:after-throwing method="afterException" pointcut-ref="logAspect"></aop:after-throwing>
<!--环绕通知-->
<!--<aop:around method="around" pointcut-ref="logAspect" arg-names="proceedingJoinPoint"></aop:around>-->
</aop:aspect>
</aop:config>
环绕通知可以实现上面的4种通知,并且可以控制业务方法是否执行。通过如下代码控制:
proceedingJoinPoint.proceed(proceedingJoinPoint.getArgs());
public class LogUtil {
public void printLog(){
System.out.println("打印日志");
}
public void after(){
System.out.println("后日志打印,不管业务是否正常");
}
public void afterReturn(){
System.out.println("正常执行完毕打印日志");
}
public void afterException(){
System.out.println("异常执行打印日志");
}
public void around(ProceedingJoinPoint proceedingJoinPoint){
System.out.println("环绕前置");
try {
Object result = proceedingJoinPoint.proceed(proceedingJoinPoint.getArgs());
System.out.println("环绕正常执行");
} catch (Throwable throwable) {
throwable.printStackTrace();
System.out.println("环绕异常执行");
}
}
}
- 切入点表达式
举例:
public void
com.lagou.service.impl.TransferServiceImpl.updateAccountByCardNo(c
om.lagou.pojo.Account)
- 访问修饰符可以省略,也就是public可以不用写
void com.mmc.ioc.service.impl.TransferServiceImpl.transfer(String,String,int)
- 返回值可以用*代替,表示返回任意值
* com.mmc.ioc.service.impl.TransferServiceImpl.transfer(String,String,int)
- 包名可以使用..表示当前包及其子包
* com..TransferServiceImpl.transfer(String,String,int)
- 类名和方法名,都可以使用*表示任意类,任意方法
* com..*(String,String,int))
- 参数列表,如果是基本类型可以直接写名称,如int。引用类型必须用全限定名称
- 参数列表可以使用*代替任意参数类型,但必须有参数
* com..*(*)
- 参数列表可以使用..代替任意参数类型,有无参数均可
* com..*(*)
- 全通配方式:
* *..*.*(..)
2.2 XML+注解模式
- XML中开启Spring对注解AOP的支持
<!--开启spring对注解aop的⽀持-->
<aop:aspectj-autoproxy/>
- 注解配置
@Component
@Aspect
public class LogUtil {
@Pointcut("execution(* com.mmc.ioc.service.impl.TransferServiceImpl.transfer(..))")
public void pointcut(){}
@Before("pointcut()")
public void printLog(){
System.out.println("打印日志");
}
@After("pointcut()")
public void after(){
System.out.println("后日志打印,不管业务是否正常");
}
@AfterReturning("pointcut()")
public void afterReturn(){
System.out.println("正常执行完毕打印日志");
}
@AfterThrowing("pointcut()")
public void afterException(){
System.out.println("异常执行打印日志");
}
// @Around("pointcut()")
public void around(ProceedingJoinPoint proceedingJoinPoint){
System.out.println("环绕前置");
try {
Object result = proceedingJoinPoint.proceed(proceedingJoinPoint.getArgs());
System.out.println("环绕正常执行");
} catch (Throwable throwable) {
throwable.printStackTrace();
System.out.println("环绕异常执行");
}
}
}
2.3 纯注解模式
只需要用注解@EnableAspectJAutoProxy替换掉
<aop:aspectj-autoproxy/>
Spring事务配置
也分为3种模式
3.1 XML模式
- 引入pom依赖
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.1.12.RELEASE</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.4</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.1.12.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>5.1.12.RELEASE</version>
</dependency>
- xml配置
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<constructor-arg name="dataSource" ref="dataSource"></constructor-arg>
</bean>
<tx:advice id="txAdice" transaction-manager="transactionManager">
<!--定制事务细节-->
<tx:attributes>
<tx:method name="*" read-only="false" propagation="REQUIRED" isolation="DEFAULT"/>
<tx:method name="query*" read-only="true" propagation="SUPPORTS"></tx:method>
</tx:attributes>
</tx:advice>
<!--事务衡器逻辑-->
<aop:config>
<aop:advisor advice-ref="txAdice" pointcut="execution(* com.mmc.ioc.service.impl.TransferServiceImpl.transfer(..))"></aop:advisor>
</aop:config>
3.2 基于XML+注解
- xml配置:
<!--spring声明式事务配置-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<constructor-arg name="dataSource" ref="dataSource"></constructor-arg>
</bean>
<tx:annotation-driven transaction-manager="transactionManager"></tx:annotation-driven>
- 在类或方法上面添加@Transactional注解
@Transactional(readOnly = true,propagation = Propagation.SUPPORTS)
3.3 纯注解
用@EnableTransactionManagement 注解替换掉
<tx:annotation-driven transaction-
manager="transactionManager"/>
即可
Spring AOP及事务配置三种模式详解的更多相关文章
- 分布式事务 Seata Saga 模式首秀以及三种模式详解 | Meetup#3 回顾
https://mp.weixin.qq.com/s/67NvEVljnU-0-6rb7MWpGw 分布式事务 Seata Saga 模式首秀以及三种模式详解 | Meetup#3 回顾 原创 蚂蚁金 ...
- Vi三种模式详解
命令行模式 (command mode/一般模式) 任何时候,不管用户处于何种模式,只要按一下“ESC”键,即可使Vi进入命令行模式:我们在shell环境(提示符为$)下输入启动Vi命令,进入编辑器时 ...
- spring AOP 之四:@AspectJ切入点标识符语法详解
@AspectJ相关文章 <spring AOP 之二:@AspectJ注解的3种配置> <spring AOP 之三:使用@AspectJ定义切入点> <spring ...
- rabbitmq五种模式详解(含实现代码)
一.五种模式详解 1.简单模式(Queue模式) 当生产端发送消息到交换机,交换机根据消息属性发送到队列,消费者监听绑定队列实现消息的接收和消费逻辑编写.简单模式下,强调的一个队列queue只被一个消 ...
- 多表连接的三种方式详解 hash join、merge join、 nested loop
在多表联合查询的时候,如果我们查看它的执行计划,就会发现里面有多表之间的连接方式.多表之间的连接有三种方式:Nested Loops,Hash Join 和 Sort Merge Join.具体适用哪 ...
- Spring4.X + spring MVC + Mybatis3 零配置应用开发框架搭建详解(1) - 基本介绍
Spring4.X + spring MVC + Mybatis3 零配置应用开发框架搭建详解(1) - 基本介绍 spring集成 mybatis Spring4.x零配置框架搭建 两年前一直在做后 ...
- [转]hibernate三种状态详解
本文来自 http://blog.sina.com.cn/u/2924525911 hibernate 三种状态详解 (2013-04-15 21:24:23) 转载▼ 分类: hibernate ...
- android中MVC,MVP和MVVM三种模式详解析
我们都知道,Android本身就采用了MVC模式,model层数据源层我们就不说了,至于view层即通过xml来体现,而 controller层的角色一般是由activity来担当的.虽然我们项目用到 ...
- Spring依赖注入三种方式详解
在讲解Spring依赖注入之前的准备工作: 下载包含Spring的工具jar包的压缩包 解压缩下载下来的Spring压缩包文件 解压缩之后我们会看到libs文件夹下有许多jar包,而我们只需要其中的c ...
随机推荐
- 面试官:为什么需要Java内存模型?
面试官:今天想跟你聊聊Java内存模型,这块你了解过吗? 候选者:嗯,我简单说下我的理解吧.那我就从为什么要有Java内存模型开始讲起吧 面试官:开始你的表演吧. 候选者:那我先说下背景吧 候选者:1 ...
- CVPR2021提出的一些新数据集汇总
前言 在<论文创新的常见思路总结>(点击标题阅读)一文中,提到过一些新的数据集或者新方向比较容易出论文.因此纠结于选择课题方向的读者可以考虑以下几个新方向.文末附相关论文获取方式. ...
- Typora配置双击图片放大功能
在Typora中,默认没有点击图片放大功能,本文就教大家如何配置该功能. 我的环境版本 Typora版本:0.11.13 LightBox版本:2.11.3 下载LightBox 可以从Github下 ...
- JVM详解(五)——运行时数据区-方法区
一.概述 1.介绍 <Java虚拟机规范>中明确说明:尽管所有的方法区在逻辑上属于堆的一部分,但一些简单的实现可能不会选择去进行垃圾收集或者进行压缩.但对于HotSpot JVM而言,方法 ...
- 微信h5跳转小程序wx-open-launch-weapp开放标签不显示(已解决)
前言: 前几天成功对接了跳转第三方小程序的功能,今天有个页面有需要对接.但是奇怪的是用的和上次一模一样的配置,但就是死活不显示wx-open-launch-weapp这个开放标签的按钮,看不到任何效果 ...
- JavaScript03
类型转换和运算符 typeof函数 检测数据类型,可以使用以下两种调用的方式: typeof 变量或表达式 typeof(变量或表达式) var n="asda"; console ...
- (课内)信安数基RSA-基础&&解密加速
RSA基本实现 首先获得N比特的伪随机数:使用Random库中内容. randint(n,m) 表示生成一个在n和m之间的随机数, **表示乘幂. getPrime找素数,or 1运算是一种优化:如果 ...
- JVM:内存结构
JVM:内存结构 说明:这是看了 bilibili 上 黑马程序员 的课程 JVM完整教程 后做的笔记 内容 程序计数器 虚拟机栈 本地方法栈 堆 方法区 直接内存 1. 程序计数器 1.1 定义 P ...
- AIApe问答机器人Scrum Meeting 5.1
Scrum Meeting 5 日期:2021年5月1日 会议主要内容概述:汇报两日工作. 一.进度情况 组员 负责 两日内已完成的工作 后两日计划完成的工作 工作中遇到的困难 李明昕 后端 Task ...
- spring cloud config的使用
在传统的应用中,我们的配置文件都是放在项目中,这个影响不大.但是在一个微服务架构的系统中,我们的微服务可能存在几十上百个,并且每个小的微服务可能又部署在多台机器上,那么这个时候如果我们的配置文件在都放 ...