SpringBoot:事务和AOP

事务

一组操作的集合,不可分割的工作单位,会被一起提交或撤销

要么同时成功,要么同时失败

实物操作

begin/start transaction 开启事务

commit 提交事务

rollback 回滚事务

eg:当我们需要保证数据的一致性,例如在删除时,删除了部门,却没有删除部门的员工,就会出现数据的不一致

此时就需要使用事务

Spring事务管理

@Transactional

在业务(service)层的方法,类,接口上

将当前方法交给Spring进行事务管理,执行前开启事务,成功执行提交事务,出现异常回滚事务.


事务进阶

rollbackfor

@Transactional的一个属性,接收异常的字节码文件

可以控制在什么异常类型下会回滚事务,默认情况下会在RuntimeException下回滚事务.

在任意异常下回滚事务:

@Transactional(rollbackFor = Exception.class)
propagation

@Transactional的一个属性,接收事务的传播行为方式

事务传播行为:指的就是当一个事务方法被另一个事务方法调用时,这个事务方法应该如何进行事务控制.

如果没有配置事务传播行为,则默认事务传播行为为REQUIRED,如果多个方法的事务传播行为相同就可以进行统一的提交和回滚.

配置事务行为
REQUIRE(常用)
//默认值,需要事务,有就加入,没有就创建新事务
REQUIRE_NEW(常用)
//需要新事务,无论有无,总是创建新事务
SUPPORTS
//支持事务,有则加入,没有就在独立连接中运行SQL
NOT_SUPPORTED
//不支持事务,不加入,在独立连接中运行SQL
MANDATORY
//必须有事务,否则抛出异常
NEVER
//必须没有事务,否则抛出异常
NESTED
//嵌套事务(仅对DataSourseTransactionManager有效)

REQUIRED:在大部分情况下适用

REQUIRED_NEW:不希望事务之间相互影响时使用

AOP

Aspect Oriented Programming(面向切面编程)

将重复的逻辑剥离出来,在不修改原始逻辑的基础上对原始功能进行增强

无侵入,减少重复代码,提高开发效率,维护方便
定义类抽取公共代码
@Aspect
标识AOP类,并且将这个类交给Spring容器管理
@Component
配置公共代码作用的方法

@Around:环绕通知

在目标方法执行前后执行公共代码

任意 *

任意参数 …


执行目标方法

使用动态代理实现AOP

当目标对象功能需要被增强时,并且我们使用AOP方式在Aspect类中定义了增强逻辑

Spring会为目标对象自动生成一个代理对象,并在代理对象对应方法中结合我们定义的AOP增强逻辑完成功能增强.


AOP核心概念

连接点:JoinPoint(可以被AOP控制的方法执行)包含方法信息

通知:Advice,重复逻辑代码

切入点:PointCut,匹配连接点的条件(execution…)

切面:Aspect,通知+切点

AOP进阶

通知类型

@Around
//此注解标注的通知方法在目标方法前后都执行
//需要自己调用ProceedingJoinPoint.proceed()方法来让目标方法执行
@Before
//此注解标注的通知方法在目标方法前被执行
@After
//此注解标注的通知方法在目标方法后被执行,无论是否存在异常
(finally块中)
@AfterReturning
//同上,但有异常时不会执行,后于@After执行
@AfterThrowing
//在发生异常后执行

AOP通知顺序

当多个切面的切点都匹配目标时,多个通知方法都会被执行

默认按照类名字母排序
用@Order(数字)加在切面类上来控制顺序

目标前的通知方法:数字小先执行 升序

目标后的通知方法:数字大先执行 降序

顺序类似于进栈出栈

切点表达式

execution(返回值类型 包名 类名 方法名(参数类型))

@annotation()根据注解匹配

args()根据方法匹配

execution

根据方法的返回值,包名,类名,方法名,方法参数等信息来匹配

execution(访问修饰符) 返回值 包名.类名.方法名(方法参数) throws 异常)

访问修饰符可省略

包名.类名可省略

throws异常:可省略(声明中抛出的异常而非方法实际抛出的异常)

annotation

切点表达式也支持匹配目标方法是否存在注解

使用@annotation

@annotation(com.itheima.anno.Log)

@Pointcut

抽取一个切入点表达式,在其他地方通过类似调用的形式对其进行引用

@Pointcut(切入点)
public void function()

@After("function()")

连接点

即目标方法,在Spring中使用JoinPoint抽象了连接点,用它可以获得方法执行时的相关信息,如方法名,方法参数类型,方法实际参数等.

对于@Around通知,获取连接点信息只能使用ProceedingJoinPoint

对应其他四种通知只能使用JoinPoint,即ProceedingJoinPoint的父类型

//获取类名
getTarget().getClass().getName()
//获取方法名
getSignature().getName()
//获取参数(返回一个Object数组)
getArgs()

案例

@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;
    }


}
  • 4
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值