事务
一组操作的集合,不可分割的工作单位,会被一起提交或撤销
要么同时成功,要么同时失败
实物操作
begin/start transaction 开启事务
commit 提交事务
rollback 回滚事务
eg:当我们需要保证数据的一致性,例如在删除时,删除了部门,却没有删除部门的员工,就会出现数据的不一致
此时就需要使用事务
Spring事务管理
@Transactional
在业务(service)层的方法,类,接口上
将当前方法交给Spring进行事务管理,执行前开启事务,成功执行提交事务,出现异常回滚事务.
事务进阶
rollbackfor
@Transactional的一个属性,接收异常的字节码文件
可以控制在什么异常类型下会回滚事务,默认情况下会在RuntimeException下回滚事务.
在任意异常下回滚事务:
java
@Transactional(rollbackFor = Exception.class)
propagation
@Transactional的一个属性,接收事务的传播行为方式
事务传播行为:指的就是当一个事务方法被另一个事务方法调用时,这个事务方法应该如何进行事务控制.
如果没有配置事务传播行为,则默认事务传播行为为REQUIRED,如果多个方法的事务传播行为相同就可以进行统一的提交和回滚.
配置事务行为
java
REQUIRE(常用)
//默认值,需要事务,有就加入,没有就创建新事务
REQUIRE_NEW(常用)
//需要新事务,无论有无,总是创建新事务
SUPPORTS
//支持事务,有则加入,没有就在独立连接中运行SQL
NOT_SUPPORTED
//不支持事务,不加入,在独立连接中运行SQL
MANDATORY
//必须有事务,否则抛出异常
NEVER
//必须没有事务,否则抛出异常
NESTED
//嵌套事务(仅对DataSourseTransactionManager有效)
REQUIRED:在大部分情况下适用
REQUIRED_NEW:不希望事务之间相互影响时使用
AOP
Aspect Oriented Programming(面向切面编程)
将重复的逻辑剥离出来,在不修改原始逻辑的基础上对原始功能进行增强
无侵入,减少重复代码,提高开发效率,维护方便
定义类抽取公共代码
java
@Aspect
标识AOP类,并且将这个类交给Spring容器管理
java
@Component
配置公共代码作用的方法
@Around:环绕通知
在目标方法执行前后执行公共代码
任意 *
任意参数 ...
执行目标方法
使用动态代理实现AOP
当目标对象功能需要被增强时,并且我们使用AOP方式在Aspect类中定义了增强逻辑
Spring会为目标对象自动生成一个代理对象,并在代理对象对应方法中结合我们定义的AOP增强逻辑完成功能增强.
AOP核心概念
连接点:JoinPoint(可以被AOP控制的方法执行)包含方法信息
通知:Advice,重复逻辑代码
切入点:PointCut,匹配连接点的条件(execution...)
切面:Aspect,通知+切点
AOP进阶
通知类型
java
@Around
//此注解标注的通知方法在目标方法前后都执行
//需要自己调用ProceedingJoinPoint.proceed()方法来让目标方法执行
@Before
//此注解标注的通知方法在目标方法前被执行
@After
//此注解标注的通知方法在目标方法后被执行,无论是否存在异常
(在finally块中)
@AfterReturning
//同上,但有异常时不会执行,后于@After执行
@AfterThrowing
//在发生异常后执行
AOP通知顺序
当多个切面的切点都匹配目标时,多个通知方法都会被执行
默认按照类名字母排序
用@Order(数字)加在切面类上来控制顺序
目标前的通知方法:数字小先执行 升序
目标后的通知方法:数字大先执行 降序
顺序类似于进栈出栈
切点表达式
execution(返回值类型 包名 类名 方法名(参数类型))
...
@annotation()根据注解匹配
args()根据方法匹配
execution
根据方法的返回值,包名,类名,方法名,方法参数等信息来匹配
java
execution(访问修饰符) 返回值 包名.类名.方法名(方法参数) throws 异常)
访问修饰符可省略
包名.类名可省略
throws异常:可省略(声明中抛出的异常而非方法实际抛出的异常)
annotation
切点表达式也支持匹配目标方法是否存在注解
使用@annotation
java
@annotation(com.itheima.anno.Log)
@Pointcut
抽取一个切入点表达式,在其他地方通过类似调用的形式对其进行引用
java
@Pointcut(切入点)
public void function()
@After("function()")
连接点
即目标方法,在Spring中使用JoinPoint抽象了连接点,用它可以获得方法执行时的相关信息,如方法名,方法参数类型,方法实际参数等.
对于@Around通知,获取连接点信息只能使用ProceedingJoinPoint
对应其他四种通知只能使用JoinPoint,即ProceedingJoinPoint的父类型
java
//获取类名
getTarget().getClass().getName()
//获取方法名
getSignature().getName()
//获取参数(返回一个Object数组)
getArgs()
案例
java
@Aspect
@Component
public class aspect {
@Autowired
LogMapper logMapper;
@Autowired
LoginControllerImpl loginController;
@Around("execution(* com.example.tlias.service.Impl.*.*(..))")
public Object caltime(ProceedingJoinPoint jp) throws Throwable{
Logs logs = new Logs();
Long start = System.currentTimeMillis();
Object returns = jp.proceed();
Long end = System.currentTimeMillis();
System.out.println("时间" + (end - start));
logs.setTime(end-start);
logs.setFunctionName(jp.getSignature().getName());
logs.setClassName(jp.getTarget().getClass().getName());
logs.setReturns(JSONObject.toJSONString(returns));
logs.setArgs(jp.getArgs().toString());
logs.setUser(loginController.id);
System.out.println("当前用户:" + logs.getUser());
logs.setOpTime(LocalDateTime.now());
logMapper.insert(logs);
return returns;
}
}