spring框架AOP、spring事管理

news/2025/1/16 5:04:54/

概念

Aspect Oriented Programming,面向切面编程是对面向对象编程的补充延续。
面向切面编程思想是将程序中非业务(提交事务、打印日志、权限验证、统一异常处理)然后在调用业务代码是,通过代理对象帮助我们调用这些提取出来的非业务代码。这样在业务代码中不用显示调用的非业务代码,做到了业务代码和非业务代码的分离,降低了耦合度。
好处:模块之间的耦合度降低了
原理:动态代理模式,给业务代码生成代理对象
AOP实现:AOP编程思想是Java中的编程思想,不是spring专有的的,是spring使用了AOP编程思想。
       AspectJ 是一个基于 Java 语言的 AOP 框架,它提供了强大的 AOP 功能,且其实
现方式更为简捷,使用更为方便, 而且还支持注解式开发。所以,Spring 又
将 AspectJ 的对于 AOP 的实现也引入到了自己的框架中
导入依赖:
<!--spring-AOP-->
<dependency><groupId>org.springframework</groupId><artifactId>spring-aspects</artifactId><version>5.2.2.RELEASE</version>
</dependency>

AOP基础知识

连接点:类中可以被增强的方法
切入点:类中实际增强的方法
通知:向连接点增加的功能。通知分为方法执行前通知、方法执行后通知、环绕通知
目标:代理的目标对象(连接点切入点所在的类)
代理:向目标对象应用通知时创建的代理对象
AspectJ常用的通知类型有五种:前置通知、后置通知、环绕通知、异常通知、返回通知。
基于注解方式的实现,在sprig.xml中进行配置
启动 AspectJ 支持:<aop:aspectj-autoproxy />
对应五种标签:
@Before 前置通知: 在业务方法执行前调用执行
 @Before("execution(* com.ffyc.springpro.Dao.AdminDao.*(..))")public void printLog(){System.out.println("打印日志");}

@After 后置通知: 在业务方法执行后调用执行 即使业务代码中出现了异常它也会执行
 @After("execution(* com.ffyc.springpro.Dao.AdminDao.*(..))")public void printLog(){System.out.println("打印日志");}

连接点:

 public void insert(){System.out.println("新增");System.out.println(10/0);}

结果,即使出现异常也会执行

@AfterReturnning 返回通知:方法成功执行之后通知,出现异常不执行
 @AfterReturning("execution(* com.ffyc.springpro.Dao.AdminDao.*(..))")public void printLog(){System.out.println("打印日志");}

连接点:

 public void insert(){System.out.println("新增");System.out.println(10/0);}

结果,即使出现异常不会执行

@AfterThrowing 异常通知:业务代码出现异常后执行,未出现异常不执行
 @AfterThrowing(value = "execution(* com.ffyc.springpro.Dao.AdminDao.*(..))",throwing = "e")public void exception(Throwable e){System.out.println("系统忙");e.printStackTrace();}

连接点:

 public void insert(){System.out.println("新增");System.out.println(10/0);}
出现异常执行

连接点:
 public void insert(){System.out.println("新增");// System.out.println(10/0);}
未出现异常不执行
@Around 环绕通知:方法执行前后都有通知
ProceedingJoinPoint  joinPoint 表示的就是目标方法
@Around("execution(* com.ffyc.springpro.Dao.AdminDao.*(..))")public void around(ProceedingJoinPoint joinPoint){System.out.println("前置通知");try {Object [] objects= joinPoint.getArgs();//获取目标方法的参数joinPoint.proceed();//调用目标业务方法System.out.println(Arrays.toString(objects));System.out.println("返回通知");} catch (Throwable throwable) {throwable.printStackTrace();System.out.println("异常通知");}System.out.println("后置通知");}

连接点

public void insert(String name){System.out.println("新增"+name);//  System.out.println(10/0);
}

结果

Spring事务管理

          事务管理本质上是数据库提供的一种管理机制。数据库在执行一次操作过程中执行的多条语句进行管理,确保多条sql要么都成功执行,要么都不执行,从而保证数据一致性。

数据库事务管理:我们在开发企业应用时,对于业务人员的一个操作实际是对数据读写的多步 操作的结合。由于数据操作在顺序执行的过程中,任何一步操作都有可能发生异 常,异常会导致后续操作无法完成,此时由于业务逻辑并未正确的完成,之前成功操作数据的并不可靠,需要在这种情况下进行回退。 事务的作用就是为了保证用户的每一个操作都是可靠的,事务中的每一步操 作都必须成功执行,只要有发生异常就回退到事务开始未进行操作的状态,这些 操作要么都完成,要么都取消,从而保证数据满足一致性的要求。

spring事务管理是spring框架对事务提交这一功能进行封装,程序员在业务开发中不需要显示的提交事务。

spring事务管理的俩种形式

1、编程式事务管理:需要程序员在代码中自己控制事务提交和回滚

2、声明式事务管理:底层使用了AOP思想,建立在AOP的基础上,可以为方法添加事务功能,它的控制是方法级别的。

基于注解方式实现spring事务管理

先在spring.xml文件中进行配置

<!-- 配置 spring 事务管理器-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><property name="dataSource" ref="druidDataSource"></property>
</bean><!-- 开启注解事务管理 -->
<tx:annotation-driven transaction-manager="transactionManager"/>
spring框架提供事务管理实现类是 DataSourceTransactionManager,然后在需要进行事务管理的类或方法上添加 @Transaction,如果添加在类上,那么类下的所有方法都会事务管理。
以方法为例
@Transactional
public void insert(){System.out.println("新增");jdbcTemplate.update("insert into admin(account,password,gender) values(?,?,?)","张三","111","男");//  System.out.println(10/0);jdbcTemplate.update("insert into admin(account,password,gender) values(?,?,?)","张三","111","男");
}

进行测试,如果出现异常,则会自动回滚事务,不出现异常,会向数据库提交。

 在实际应用场景中,我们不会将@Transaction添加到dao层(数据访问层),而是添加到service层(业务逻辑层),因为在dao层,方法是执行的是一条sql语句,而service层的方法中会掉用多个dao层的方法,如果添加在了dao层,service层的方法出现了异常,spring还是会将事务提交。

示例:

dao层:

@Transactionalpublic void insert1(){jdbcTemplate.update("insert into admin(account,password,gender) values(?,?,?)","张三1","111","男");}@Transactionalpublic void insert2(){jdbcTemplate.update("insert into admin(account,password,gender) values(?,?,?)","张三2","111","男");}

service层:

 public void insertAdmin(){adminDao.insert1();System.out.println(10/0);adminDao.insert2();}

 service层的方法出现了异常,原则上是不能将数据提交的数据库的,但是我们 程序还是进行了事务提交。

执行结果:出现了异常

为了解决这一问题,所有我们将@Transaction添加到service层。

@Transactional(rollbackFor = Exception.class)public void insertAdmin(){adminDao.insert1();System.out.println(10/0);adminDao.insert2();}

出现异常则不会提交事务。

声明式事务管理失效场景:

1、@Transactional用在非public方法上,在底层实现上是Java的反射机制,getMethod只能获得是公共方法(public方法),非public方法不能够得到

2、方法中出现异常被catch捕获,那么就会认为没有异常出现

3、方法中出现了编译期异常,还是会提交事务的,可以将@Transactional(rollbackFor = Exception.class)这样所有的异常都会回滚事务

4、数据库引擎不支持事务,mysql中只有innodb引擎支持事务

 

http://www.ppmy.cn/news/1519496.html

相关文章

SecurityHeaders:为.Net网站添加安全标头,让Web更加安全、避免攻击!

网站的安全对于任何一家公司都是非常重要的。 为了保证Web安全&#xff0c;其中Http安全标头就是非常重要一个的措施。设定正确的安全头可以增强网站的安全性&#xff0c;因为它们可以帮助防止各种网络攻击&#xff0c;如跨站脚本&#xff08;XSS&#xff09;、点击劫持&#…

算法-汇总区间(228)

这题可以用区间来做&#xff0c;区间是什么&#xff0c;在编程问题中&#xff0c;区间常用于表示连续的数字集合&#xff0c;比如这道题【0&#xff0c;2】就表示0&#xff0c;1&#xff0c;2这样的数字集合。 所以这道题首先定义一个字符数组用来存输出结果&#xff0c;然后定…

Datawhale X 李宏毅苹果书 AI夏令营|机器学习基础之线性模型

1. 线性模型 线性模型是机器学习中最基础和常见的模型之一。在线性模型中&#xff0c;预测变量&#xff08;输入特征&#xff09;和目标变量&#xff08;输出&#xff09;之间的关系被建模为一个线性组合。数学形式可以表示为&#xff1a; 其中&#xff1a;x 是输入特征向量&a…

Linux平台中标麒麟安装单机DM8数据库

1 说明 数据库是现代信息化系统的基石&#xff0c;而国产数据库的发展则关乎国家的信息安全和国民经济的命脉。达梦数据库作为中国数据库领域的领军企业&#xff0c;其DM8数据库管理系统凭借其高性能、高可靠性、易用性等特点&#xff0c;逐渐赢得了用户的青睐。 本文详细介绍…

【开源免费】基于SpringBoot+Vue.JS渔具租赁系统(JAVA毕业设计)

本文项目编号 T 005 &#xff0c;文末自助获取源码 \color{red}{T005&#xff0c;文末自助获取源码} T005&#xff0c;文末自助获取源码 目录 一、系统介绍二、演示录屏三、启动教程四、功能截图五、文案资料5.1 选题背景5.2 国内外研究现状5.3 可行性分析 六、核心代码6.1 渔…

牛牛替换(c语言)

1.//描述 //牛牛有一个长度为 n 的字符数组&#xff0c;他尝试把字符数组中其中一些字符替换成另一些字符。 //输入描述&#xff1a; //第一行输入一个正整数 n 表示字符数组的长度&#xff0c;四个个字符分别 a1 和 a2 &#xff0c; a3 和 a4&#xff0c; // 表示把字符数组中…

数据结构代码集训day8(适合考研、自学、期末和专升本)

习题来自B站up&#xff1a;白话拆解数据结构! 题目如下&#xff1a; &#xff08;1&#xff09;在递增有序的单链表L中&#xff0c;删除值重复的结点 &#xff08;2&#xff09;使带头节点单链表的值递增有序 题1 和之前顺序表那题差不多&#xff0c;因为是有序的&#xff0c…

生成图片的base64编码(纯C语言实现)

一、前言 Base64编码是一种广泛使用的编码方案&#xff0c;将任意二进制数据转换为可打印的ASCII字符字符串。这种编码方式之所以重要&#xff0c;是因为许多通信协议和存储介质对数据的可传输性和可存储性有特定的要求&#xff0c;它们可能无法直接处理或有效传输二进制数据。…