JavaWeb学习——事务管理、AOP学习

news2024/9/24 11:23:56

目录

一、事务管理

1、事务回顾

 2、事务进阶

a、rollbackFor属性

b、propagation属性

二、AOP学习

1、基础了解

2、AOP进阶


一、事务管理

1、事务回顾

        事务的概念:事务必须服从ACID原则。ACID指的是原子性(atomicity)、一致性(consistency)、隔离性(isolation)和持久性(durability)。通俗理解,事务其实就是一系列指令的集合。

        事务的特性

        原子性:操作这些指令时,要么全部执行成功,要么全部不执行。只要其中一个指令执行失败,所有的指令都执行失败,数据进行回滚,回到执行指令前的数据状态。
        一致性:事务的执行使数据从一个状态转换为另一个状态,但是对于整个数据的完整性保持稳定。
        隔离性:在该事务执行的过程中,无论发生的任何数据的改变都应该只存在于该事务之中,对外界不存在任何影响。只有在事务确定正确提交之后,才会显示该事务对数据的改变。其他事务才能获取到这些改变后的数据。
        持久性:当事务正确完成后,它对于数据的改变是永久性的。

下面提供一个事务操作发生的图进行述说:

        感想:其实联系我之前学习的MySql知识,可以发现此事务就是当时学习到的事务概念,主要的是对数据库操作进行一个集合类的统合,实现数据的同步修改性。

接下来举一个案例来说明使用事务的原因

        分析:上图是一个对部门表实现删除部门的代码案例,首先它能实现基础的连带部门信息和部门人员信息的删除,但当代码执行过程中出现异常,如上图设置的1/0,就会中断代码执行,在前端表现就是只删除了部门信息,数据库里也是如此,它们不能一致的发生删除或不删除,由此我们就要利用到事务来进行管理,实现同步。

使用注释,进行事务集合使用(@Transactional)

        分析:由图可知该注释可以使用在方法、类、接口上,自由度很高,而要解决上面提到的问题,只要在方法上实现就行。

补充:spring事务管理日志依赖添加

        添加原因:Spring 事务管理是 Spring 框架中一个重要的模块,它提供了强大的事务管理能力,使得我们可以对事务操作进行细粒度的控制。

        添加代码

#spring事务管理日志
logging:
  level:
    org.springframework.jdbc.support.JdbcTransactionManager: debug

 2、事务进阶

a、rollbackFor属性

        作用:在 Spring 数据访问操作中,默认情况下只有未检查(unchecked)异常(继承自 RuntimeException 的异常)或者 Error 会导致事务回滚,而受检查的异常(即非 RuntimeException 异常)则不会导致事务回滚。rollbackFor 属性就是用来解决这个问题的,它可以指定受检查的异常也可以导致事务回滚。你可以设置任何你希望导致此行为的异常类型。

代码示例

 @Transactional(rollbackFor = Exception.class) //spring事务管理
    //@Transactional
    @Override
    public void delete(Integer id) throws Exception {
        try {
            deptMapper.deleteById(id); //根据ID删除部门数据

            int i = 1/0;
            //if(true){throw new Exception("出错啦...");}

            empMapper.deleteByDeptId(id); //根据部门ID删除该部门下的员工
        } finally {
            DeptLog deptLog = new DeptLog();
            deptLog.setCreateTime(LocalDateTime.now());
            deptLog.setDescription("执行了解散部门的操作,此次解散的是"+id+"号部门");
            deptLogService.insert(deptLog);
        }
    }

        分析:上图代码的效果仍是删除部门相关信息,只是最后的完成版,在这我们不用太在意另外的代码,只用看@Transactional后面括号里的rollbackFor使用,这里是指定所有的异常,我们也可以换另外的指定异常类型。

b、propagation属性

        作用propagation 是 Spring 的 @Transactional 注解的一个属性,它用于指定事务的传播行为。事务的传播行为决定了在方法被调用时,事务是如何沿着调用链传播的。

使用类型

  1. REQUIRED(Propagation.REQUIRED):如果当前存在事务,则加入该事务;如果当前没有事务,则创建一个新的事务。这是默认的设置。

  2. SUPPORTS(Propagation.SUPPORTS):如果当前存在事务,则加入该事务;如果当前没有事务,则以非事务的方式继续运行。

  3. MANDATORY(Propagation.MANDATORY):如果当前存在事务,则加入该事务;如果当前没有事务,则抛出异常。

  4. REQUIRES_NEW(Propagation.REQUIRES_NEW):创建一个新的事务,如果当前存在事务,则把当前事务挂起。

  5. NOT_SUPPORTED(Propagation.NOT_SUPPORTED):以非事务方式运行操作,如果当前存在事务,就把当前事务挂起。

  6. NEVER(Propagation.NEVER):以非事务方式运行,如果当前存在事务,则抛出异常。

  7. NESTED(Propagation.NESTED):如果当前存在事务,则创建一个事务作为当前事务的嵌套事务来运行;如果当前没有事务,则该取值等价于 REQUIRED

使用视图

 

        感想:这一属性的使用就是可以自由设置当多重事务关联触发时,我们来决定它们的运行顺序和存在周期。

二、AOP学习

1、基础了解

AOP的概述

        AOP(Aspect Oriented Programming,面向切面编程)是一种编程范式,旨在促进更高效、组织性更好的代码。这种模式主要聚焦于程序逻辑的横向关注点,也就是那些几乎出现在所有层级代码中的公共功能(例如日志、事务管理等),而这种功能在没有 AOP 的情况下,往往需要重复编写,这会导致代码冗余。

以下是 AOP 的主要概念

  1. Aspect(切面):一个模块,具有一组提供公共功能的 APIs。在 AOP 中,切面用于封装每个横切关注点的逻辑,这些逻辑可以在运行时动态地应用到不同的对象和函数上。

  2. Join Point(连接点):程序执行过程中的某个特定点,如方法被调用时、异常被抛出时等。在 Spring AOP 中,一个连接点总是代表一个方法的执行。

  3. Advice(通知):是切面必须完成的工作,也就是切面的具体行为。根据其所在位置,通知的类型有 before、after、around、afterThrowing、afterReturning 等。

  4. Pointcut(切入点):匹配连接点的规则或概述。在 Spring AOP 中,切入点可以使用 AspectJ 的切入点表达式语言来指定。

  5. Target Object(目标对象):被一个或多个切面所通知的对象。

  6. Weaving(织入):将切面和其它应用类型或者对象连接起来,创建一个被通知的对象。这可以在编译时(使用 AspectJ 编译器),类加载时,或在运行时完成。

        Spring AOP 框架将这些概念与 Spring 的 IoC(Inversion of Control,控制反转)容器和 Spring 提供的其它功能无缝集成,从而提供了一个完整、易用,而且与 Java 语言和 Spring 框架高度集成的 AOP 实现。

应用场景

        AOP(面向切面编程)在许多编程场景中都能发挥重要作用,主要因为它有助于代码的解耦和重复代码的减少。以下是一些 AOP 常见的应用场景:

  1. 日志记录:通过把日志记录的功能放到切面中处理,可以简化主要业务逻辑代码的清晰度,并且可以非常方便地控制日志记录的粒度和范围。

  2. 事务管理:在许多企业级应用中,事务管理是一项关键任务。AOP 可以简化事务操作,通过预定义的策略,使开发者可以透明地管理和配置事务。

  3. 性能监控:AOP 可以用于收集方法调用的统计信息,例如:方法调用的次数以及每次调用的持续时间等。这些信息可以用于后续的性能分析和优化。

  4. 安全检查:可以用AOP实现统一的安全检查,避免在每个需要进行安全检查的方法中单独实现。

  5. 错误处理:可以通过 AOP 对所有方法进行统一的错误捕获和处理,减少重复的错误处理代码。

  6. 缓存:可以通过 AOP 实现方法结果的缓存,提高系统的性能。

  7. 验证和格式化:AOP 可以用于验证对象的状态或格式化对象的输出,将这些横切关注点从主要任务中分离出来。

以上是 AOP 最常见的应用场景,但是并不受此限。

Spring AOP与动态代理

Spring AOP(面向切面编程)在它的底层实现上主要使用了动态代理。

        动态代理是一种设计模式,主要是用于接口的非入侵式代理,不改变类文件和原有业务逻辑的情况下,增加额外的功能。Java的java.lang.reflect包中提供的Proxy类和InvocationHandler接口,就是用于生成动态代理类和处理代理方法调用的。

Spring AOP 使用了两种类型的动态代理:

1. **JDK动态代理**:基于接口的动态代理,JDK动态代理通过实现InvocationHandler接口,并重写invoke方法来处理代理逻辑。如果目标对象有接口,Spring AOP会选择使用JDK动态代理。

2. **CGLIB代理**:基于类的动态代理,CGLIB通过生成目标类的子类来处理代理逻辑。如果目标对象没有实现任何接口,Spring AOP会选择使用CGLIB代理。

在Spring AOP中,切面的逻辑(例如事务管理、日志记录等)通常会写在Advice中,然后这些通知会被动态织入到你指定的方法上,这样在调用这些方法时,就会执行对应的通知逻辑。

        总的来说,动态代理构成了Spring AOP的核心,Spring通过动态代理技术实现了其强大的面向切面编程功能。

举例说明(统计各个业务层方法执行耗时)

在实现AOP的使用前,我们要加入依赖:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-aop</artifactId>
</dependency>

 编写的AOP使用案例代码(实现统计执行耗时)

package com.sunny.aop;

import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;

@Slf4j
@Component
@Aspect //AOP类
public class TimeAspect {

    @Around("execution(* com.sunny.service.impl.DeptServiceImpl.*(..))") //切入点表达式
    //@Around("com.sunny.aop.MyAspect1.pt()")
    public Object recordTime(ProceedingJoinPoint joinPoint) throws Throwable {
        //1. 记录开始时间
        long begin = System.currentTimeMillis();

        //2. 调用原始方法运行
        Object result = joinPoint.proceed();

        //3. 记录结束时间, 计算方法执行耗时
        long end = System.currentTimeMillis();
        log.info(joinPoint.getSignature()+"方法执行耗时: {}ms", end-begin);

        return result;
    }

}

AOP的主要概念联系

这里提到的主要概念就是上面的主要概念,接下来举一个例子来进行说明。

以下是这些概念在一次典型的AOP操作中如何协同工作的示例:

  1. 定义一个Aspect,例如日志切面,将日志记录通知(Advice)与切入点(Pointcut,例如全部的服务操作方法)关联起来。

  2. 当程序执行到切入点的方法时,即触发了连接点(Join point),例如调用服务操作。

  3. 由于切面的存在,切入点的方法会被切面中的通知Advice捕获,这时候,日志切面的日志记录代码就在目标方法执行之前或之后执行,这个过程就是织入(Weaving)。

        总结起来,AOP的核心概念关联使用,可以使系统的服务模块关注于核心业务,而像日志,事务,安全等服务可以通过AOP的方式进行模块化和集中管理,提高了系统的可维护性和可重用性。

补充:Advice的使用类型

有以下几种类型的advice:

  1. Before advice:在切入点选择的连接点之前执行的通知(比如,一个特定的方法调用之前)。
  2. After returning advice:在切入点选择的连接点成功完成后,例如,方法成功返回结果后,执行的通知。
  3. After throwing advice:在方法抛出异常退出时执行的通知。
  4. After (finally) advice:当切入点结束后执行的通知,无论方法退出是正常还是异常返回。
  5. Around advice:包围着被通知的方法,可以在被通知的方法前后自定义行为。

        这些advice中,我们自定义的代码就是那些横切关注点的实现, 例如在方法调用前记录日志(Before advice),在方法异常时发送通知(After throwing advice)等。

下面给些代码案例

package com.sunny.aop;

import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;

@Slf4j
@Component
//@Aspect
public class MyAspect1 {

    @Pointcut("execution(* com.sunny.service.impl.DeptServiceImpl.*(..))")
    //使用切入,指定表达式
    public void pt(){}

    @Before("pt()")//Advice使用
    public void before(){
        log.info("before ...");
    }

    @Around("pt()")//Advice使用
    public Object around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        log.info("around before ...");

        //调用目标对象的原始方法执行
        Object result = proceedingJoinPoint.proceed();

        log.info("around after ...");
        return result;
    }

    @After("pt()")//Advice使用
    public void after(){
        log.info("after ...");
    }

    @AfterReturning("pt()")//Advice使用
    public void afterReturning(){
        log.info("afterReturning ...");
    }

    @AfterThrowing("pt()")//Advice使用
    public void afterThrowing(){
        log.info("afterThrowing ...");
    }
}

2、AOP进阶

@Around的使用补充

@Pointcut的使用图示

多个切点的通知顺序分析(多个切面的切入点匹配到了相同的目标方法)

切入点表达式学习

常见形式

execution详细使用

代码示例

@Pointcut("execution(public void com.itheima.service.impl.DeptServiceImpl.delete(java.lang.Integer))")
    @Pointcut("execution(void com.itheima.service.impl.DeptServiceImpl.delete(java.lang.Integer))")
    @Pointcut("execution(void delete(java.lang.Integer))") //包名.类名不建议省略
    @Pointcut("execution(void com.itheima.service.DeptService.delete(java.lang.Integer))")

    @Pointcut("execution(void com.itheima.service.DeptService.*(java.lang.Integer))")
    @Pointcut("execution(* com.*.service.DeptService.*(*))")
    @Pointcut("execution(* com.itheima.service.*Service.delete*(*))")

    @Pointcut("execution(* com.itheima.service.DeptService.*(..))")
    @Pointcut("execution(* com..DeptService.*(..))")
    @Pointcut("execution(* com..*.*(..))")
    @Pointcut("execution(* *(..))") //慎用

annotation详细使用

代码示例

package com.sunny.aop;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * 创建名为MyLog的切入点
 */
@Retention(RetentionPolicy.RUNTIME) //描述注解什么时候使用到
@Target(ElementType.METHOD) //描述注解的使用对象——方法
public @interface MyLog {
}


@MyLog //加入设定的annotation注解
    @Override
    public List<Dept> list() {
        List<Dept> deptList = deptMapper.list();
        return deptList;
    }

    @MyLog //加入设定的annotation注解
    @Override
    public void delete(Integer id) {
        //1. 删除部门
        deptMapper.delete(id);
    }

连接点使用

代码案例

package com.sunny.aop;

import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;

import java.util.Arrays;

//切面类
@Slf4j
@Aspect
@Component
public class MyAspect8 {

    @Pointcut("execution(* com.sunny.service.DeptService.*(..))")
    private void pt(){}

    @Before("pt()")
    public void before(JoinPoint joinPoint){
        log.info("MyAspect8 ... before ...");
    }

    @Around("pt()")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
        log.info("MyAspect8 around before ...");

        //1. 获取 目标对象的类名 .
        String className = joinPoint.getTarget().getClass().getName();
        log.info("目标对象的类名:{}", className);

        //2. 获取 目标方法的方法名 .
        String methodName = joinPoint.getSignature().getName();
        log.info("目标方法的方法名: {}",methodName);

        //3. 获取 目标方法运行时传入的参数 .
        Object[] args = joinPoint.getArgs();
        log.info("目标方法运行时传入的参数: {}", Arrays.toString(args));

        //4. 放行 目标方法执行 .
        Object result = joinPoint.proceed();

        //5. 获取 目标方法运行的返回值 .
        log.info("目标方法运行的返回值: {}",result);

        log.info("MyAspect8 around after ...");
        return result;
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2074137.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Linux网络编程:多路转接--poll/epoll

1. poll poll也是一种多路转接的方案&#xff0c;解决了select的fd有上限和每次调用都要重新设置关心的fd的问题。 2. poll接口 #include int poll(struct pollfd* fds, nfds_t nfds, int timeout); 参数&#xff1a;fds&#xff1a;可以看成是动态数组/数组/结构体数组 nfds&…

【生日视频制作】一群美女挥手拉蓝横幅条幅AE模板修改文字软件生成器教程特效素材【AE模板】

一群美女挥手拉蓝条横幅生日视频制作教程AE模板修改文字生成器 怎么如何做的【生日视频制作】一群美女挥手拉蓝横幅条幅AE模板修改文字软件生成器教程特效素材【AE模板】 生日视频制作步骤&#xff1a; 安装AE软件下载AE模板把AE模板导入AE软件修改图片或文字渲染出视频

Ai+若依(系统工具-->表单构建):【02篇】

系统工具 表单构建 介绍 允许用户通过拖放等可视化操作创建表单,比如用来收集数据的表格或调查问卷。 可以自定义表单的各个部分,比如添加不同的输入项和设置验证规则,无需编写代码。 提供了导出数据、导入数据、分享表单和设置权限的功能,方便数据管理和共享。 案例 通…

RoboCopy文件快速拷贝工具

RoboCopy是Windows平台(从Windows Vista/Window 7开始)自带的文件快速拷贝工具,它是xcopy命令工具的升级版,解除了xcopy拷贝文件时4GB的容量限制,同时,又支持多线程、给文件夹制作镜像、复制指定日期的文件等功能。 1 全部拷贝 假设从alice文件夹,全部拷贝到bob文件夹,则…

leetcode 80 删除有序数组中的重复项 II

正文 仍旧使用双指针&#xff0c; 思想与 leetcode 26 删除有序数组中的重复项 一致。只是此时因为要求保留重复元素两次&#xff0c;我们的左侧指针可以从第二个数据开始&#xff0c;且右侧指针需要和两个元素的值进行判断。 class Solution:def removeDuplicates(self, nums…

WPF—资源的使用

资源的使用 资源是可以在应用中的不同位置重复使用的对象。 资源的示例包括画笔和样式。 <Window.Resources><!--定义颜色资源--><SolidColorBrush x:Key"MyBrush" Color"#05E0E9"/><!--定义样式资源--><Style TargetType&quo…

前端技术(五)—— 使用Node.js编写简单的项目

一、 初始化项目 1. 创建项目 ⑴ 新建 api_kjzt_server 文件夹作为项目根目录&#xff0c;并初始化包管理配置文件 并在项目根目录中运行如下的命令&#xff0c;初始化包管理配置文件&#xff1a; npm init -y⑵ 运行如下的命令&#xff0c;安装特定版本的 express npm i e…

企业级WEB应用服务器TOMCAT详解

一、什么是TOMCAT 1.1来源 Tomcat是Apache 软件基金会&#xff08;Apache Software Foundation&#xff09;的Jakarta 项目中的一个核心项目&#xff0c;由Apache、Sun 和其他一些公司及个人共同开发而成。由于有了Sun 的参与和支持&#xff0c;最新的Servlet 和JSP 规范总是能…

A Neural Probabilistic Language Model

摘要 统计语言建模的一个目标是学习单词序列的联合概率函数。由于维度的诅咒&#xff0c;这在本质上是困难的:我们建议用它自己的武器来对抗它。在提出的方法中&#xff0c;人们同时学习(1)每个单词的分布式表示&#xff08;词向量&#xff09;(即单词之间的相似性)以及(2)表示…

TypeScript 类型注解(二)

一、TypeScript类型约束--对象 对象其实和数组类似&#xff0c;不是限制对象本身的类型&#xff0c;而是对对象属性类型进行限制 结构简化&#xff1a; 对对象做类型限制的好处&#xff1a; 大家都学习过一段时间编程了&#xff0c;会发现咱们经常操作的类型就是对象&#xf…

使用miniconda构建数据科学环境

背景 数据科学中&#xff0c;不同时期项目代码往往是由不同的版本的python和第三方数据科学包构建&#xff0c;这些不同版本往往会存在兼容性问题&#xff0c;要运行这些代码&#xff0c;需要管理不同的版本的安装包。Conda是一个开源的包管理和环境管理系统&#xff0c;环境管…

Linux | 编译和使用自定义动静态库的全面解析

新竹高于旧竹枝&#xff0c;全凭老干为扶持。 - 《新竹》(郑燮) 2024.8.25 目录 1、静态库和动态库简介 静态库&#xff08;.a&#xff09;&#xff1a; 动态库&#xff08;.so&#xff09;&#xff1a; 动态库和静态库的比较&#xff1a; 2、静态库的生成和使用&#xff…

GCB | 首次揭示!气候变化对常绿和落叶植物物候差异化影响的机制

气候变化引起的植物物候改变已对全球范围内生物多样性和生态系统产生重大影响&#xff08;Nature高引文章 | 北京大学朴世龙院士等&#xff1a;全球变暖对植被物候的影响及其机制&#xff1b;Nature Ecology & Evolution | 南京大学张永光教授团队揭示延长的植被物候期受CO…

set容器的所有操作

1.基本概念 2.构造和赋值 3.大小和交换 4.插入和删除 5.查找和统计 6.set和multiset的区别 7.pair对组创建 用p.first和p.second调用前后两个属性。 8.仿函数实现降序排列 自定义数据类型也一样用仿函数&#xff1a;

【领域驱动设计 打通DDD最小闭环】领域建模

本篇BLOG为DDD流程的第二步&#xff0c;在模型的建立阶段&#xff0c;领域专家与技术人员通过领域建模来完成更为细致的模型建立讨论 领域建模的目的 领域建模主要有两个目的&#xff1a; 将知识可视化&#xff0c;准确、深刻地反映领域知识&#xff0c;并且在业务和技术人…

Python优化算法14——海鸥优化算法(SOA)

科研里面优化算法都用的多&#xff0c;尤其是各种动物园里面的智能仿生优化算法&#xff0c;但是目前都是MATLAB的代码多&#xff0c;python几乎没有什么包&#xff0c;这次把优化算法系列的代码都从底层手写开始。 需要看以前的优化算法文章可以参考&#xff1a;Python优化算…

【图文并茂】ant design pro 如何给后端发送 json web token - 请求拦截器的使用

上一节有讲过 【图文并茂】ant design pro 如何对接后端个人信息接口 还差一个东西&#xff0c;去获取个人信息的时候&#xff0c;是要发送 token 的&#xff0c;不然会报 403. 就是说在你登录之后才去获得个人信息。这样后端才能知道是谁的信息。 token 就代码了某个人。 …

工作实战-项目压测记录

1-1-1每分钟的单量 1-1-2第二版测试 2022年5月16日 17:43:11 成功 失败 其它(nginx) 真实入库单量 总单量 52 1 447 500 2022年5月16日 19:42:18 成功 失败 其它(nginx) 真实入库单量 总单量 311 689 306 1000 2-0-1. 20线程-2000单执行结果 2-1-0. 40线…

金融科技 API 接口:提升金融服务效率的关键

金融科技是应用技术手段和创新理念来提升金融服务效率的重要途径。而其中的API接口则是实现金融科技的关键。API接口的简单定义是提供计算机程序之间通信的规范和工具&#xff0c;提供一种方法和数据的交互形式&#xff0c;以便开发人员能够利用现有的软件来创建新的应用和服务…

前端网格布局display: grid;

display: grid; 块级网格 &#xff08;常用&#xff09; display: inline-grid; 行内块级网格 &#xff08;一般不用&#xff09; HTML 元素将 display 属性设置为 grid 或 inline-grid 后&#xff0c;它就变成了一个网格容器&#xff0c;这个元素的所有直系子元素将…