• 事务管理 &AOP


    一、Spring事务管理

    1.@Transactional//Spring 事务管理

    2.事务进阶

    1.事务属性-回滚(rollbackFor)

    2.传播属性(propagation)

    1.DeptLog日志对象

    1. import lombok.AllArgsConstructor;
    2. import lombok.Data;
    3. import lombok.NoArgsConstructor;
    4. import java.time.LocalDateTime;
    5. @Data
    6. @NoArgsConstructor
    7. @AllArgsConstructor
    8. public class DeptLog {
    9. private Integer id;
    10. private LocalDateTime createTime;
    11. private String description;
    12. }

    2.DeptService层

    1. /**
    2. * 根据ID删除部门
    3. * @param id
    4. */
    5. @Transactional(rollbackFor = Exception.class)//Spring 事务管理
    6. @Override
    7. public void delete(Integer id) throws Exception {
    8. try {
    9. deptMapper.delete(id);
    10. empMapper.deleteByDeptId ( id );//根据部门Id删除该部门的员工
    11. int i= 1/0;
    12. // if (true){
    13. // throw new Exception ("出错啦");
    14. // }
    15. } finally {
    16. DeptLog deptLog =new DeptLog ();
    17. deptLog.setCreateTime ( LocalDateTime.now () );
    18. deptLog.setDescription ( "执行了解散部门的操作,此次解散的是"+id+"号部门" );
    19. deptLogService.insert ( deptLog );
    20. }

    3.DeptLogService层

    1. import com.itheima.mapper.DeptLogMapper;
    2. import com.itheima.pojo.DeptLog;
    3. import com.itheima.service.DeptLogService;
    4. import org.springframework.beans.factory.annotation.Autowired;
    5. import org.springframework.stereotype.Service;
    6. import org.springframework.transaction.annotation.Propagation;
    7. import org.springframework.transaction.annotation.Transactional;
    8. @Service
    9. public class DeptLogServiceImpl implements DeptLogService {
    10. @Autowired
    11. private DeptLogMapper deptLogMapper;
    12. @Transactional(propagation = Propagation.REQUIRES_NEW)
    13. @Override
    14. public void insert(DeptLog deptLog) {
    15. deptLogMapper.insert(deptLog);
    16. }
    17. }

    4.DeptLogMapper层

    1. import com.itheima.pojo.DeptLog;
    2. import org.apache.ibatis.annotations.Insert;
    3. import org.apache.ibatis.annotations.Mapper;
    4. @Mapper
    5. public interface DeptLogMapper {
    6. @Insert("insert into dept_log(create_time,description) values(#{createTime},#{description})")
    7. void insert(DeptLog log);
    8. }

    5.数据库层

    1. create table dept_log(
    2. id int auto_increment comment '主键ID' primary key,
    3. create_time datetime null comment '操作时间',
    4. description varchar(300) null comment '操作描述'
    5. )comment '部门操作日志表';

    二、AOP-面向切面编程

    1.AOP基础

    1. import lombok.extern.slf4j.Slf4j;
    2. import org.aspectj.lang.ProceedingJoinPoint;
    3. import org.aspectj.lang.annotation.Around;
    4. import org.aspectj.lang.annotation.Aspect;
    5. import org.springframework.stereotype.Component;
    6. @Slf4j
    7. @Component
    8. @Aspect//AOP类
    9. public class TimeAspect {
    10. @Around ( "execution(* com.itheima.service.*.*(..))" )//切入点表达式
    11. public Object recordTime(ProceedingJoinPoint joinPoint) throws Throwable {
    12. //1.记录开始时间
    13. long begin = System.currentTimeMillis ();
    14. //2.调用原始方法运行
    15. Object result = joinPoint.proceed ();
    16. //3.记录结束时间,计算方法执行耗时
    17. long end = System.currentTimeMillis ();
    18. log.info (joinPoint.getSignature ()+ "方法执行耗时:{}ms",end-begin );
    19. return result;
    20. }
    21. }

    2.AOP核心概念

    1.概念

    2.AOP的执行流程

    3.AOP进阶

    1.通知类型

    1. import lombok.extern.slf4j.Slf4j;
    2. import org.aspectj.lang.ProceedingJoinPoint;
    3. import org.aspectj.lang.annotation.*;
    4. import org.springframework.stereotype.Component;
    5. @Slf4j
    6. @Aspect
    7. @Component
    8. public class MyAspect1 {
    9. //抽取切入点表达式
    10. @Pointcut("execution(* com.itheima.service.impl.DeptServiceImpl.*(..))")
    11. public void p(){}
    12. @Before ("p()" )
    13. public void before(){
    14. log.info ( "before..." );
    15. }
    16. @Around ( "p()" )
    17. public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
    18. log.info ( "around before..." );
    19. //调用目标对象的原始方法执行
    20. Object result = joinPoint.proceed ();
    21. log.info ( "around..." );
    22. return result;
    23. }
    24. @After ("p()" )
    25. public void after(){
    26. log.info ( "after..." );
    27. }
    28. @AfterReturning("p()")
    29. public void afterReturning(){
    30. log.info ( "afterReturning..." );
    31. }
    32. @AfterThrowing("p()")
    33. public void afterThrowing(){
    34. log.info ( "afterThrowing" );
    35. }
    36. }

    2.通知的执行顺序

    3.切入点表达式

    1.execution(.....)

    2.@annotation

    4.连接点

    1. import lombok.extern.slf4j.Slf4j;
    2. import org.aspectj.lang.JoinPoint;
    3. import org.aspectj.lang.ProceedingJoinPoint;
    4. import org.aspectj.lang.annotation.Around;
    5. import org.aspectj.lang.annotation.Aspect;
    6. import org.aspectj.lang.annotation.Before;
    7. import org.aspectj.lang.annotation.Pointcut;
    8. import org.springframework.stereotype.Component;
    9. import java.util.Arrays;
    10. //切面类
    11. @Slf4j
    12. @Aspect
    13. @Component
    14. public class MyAspect8 {
    15. @Pointcut("execution(* com.itheima.service.DeptService.*(..))")
    16. private void pt(){}
    17. @Before("pt()")
    18. public void before(JoinPoint joinPoint){
    19. log.info("MyAspect8 ... before ...");
    20. }
    21. @Around("pt()")
    22. public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
    23. log.info("MyAspect8 around before ...");
    24. //1. 获取 目标对象的类名 .
    25. String className = joinPoint.getTarget().getClass().getName();
    26. log.info("目标对象的类名:{}", className);
    27. //2. 获取 目标方法的方法名 .
    28. String methodName = joinPoint.getSignature().getName();
    29. log.info("目标方法的方法名: {}",methodName);
    30. //3. 获取 目标方法运行时传入的参数 .
    31. Object[] args = joinPoint.getArgs();
    32. log.info("目标方法运行时传入的参数: {}", Arrays.toString(args));
    33. //4. 放行 目标方法执行 .
    34. Object result = joinPoint.proceed();
    35. //5. 获取 目标方法运行的返回值 .
    36. log.info("目标方法运行的返回值: {}",result);
    37. log.info("MyAspect8 around after ...");
    38. return result;
    39. }
    40. }

    三、AOP综合案例

    1.引入依赖

    1. <dependency>
    2. <groupId>org.springframework.bootgroupId>
    3. <artifactId>spring-boot-starter-aopartifactId>
    4. dependency>

    2.设置自定义注解

    1. import java.lang.annotation.ElementType;
    2. import java.lang.annotation.Retention;
    3. import java.lang.annotation.RetentionPolicy;
    4. import java.lang.annotation.Target;
    5. @Retention ( RetentionPolicy.RUNTIME )
    6. @Target ( ElementType.METHOD )
    7. public @interface Log {
    8. }

    3.日志类对象

    1. import lombok.AllArgsConstructor;
    2. import lombok.Data;
    3. import lombok.NoArgsConstructor;
    4. import java.time.LocalDateTime;
    5. @Data
    6. @NoArgsConstructor
    7. @AllArgsConstructor
    8. public class OperateLog {
    9. private Integer id; //ID
    10. private Integer operateUser; //操作人ID
    11. private LocalDateTime operateTime; //操作时间
    12. private String className; //操作类名
    13. private String methodName; //操作方法名
    14. private String methodParams; //操作方法参数
    15. private String returnValue; //操作方法返回值
    16. private Long costTime; //操作耗时
    17. }

    4.AOP类

    1. import com.alibaba.fastjson.JSONObject;
    2. import com.itheima.mapper.OperateLogMapper;
    3. import com.itheima.pojo.OperateLog;
    4. import com.itheima.utils.JwtUtils;
    5. import io.jsonwebtoken.Claims;
    6. import lombok.extern.slf4j.Slf4j;
    7. import org.aspectj.lang.ProceedingJoinPoint;
    8. import org.aspectj.lang.annotation.Around;
    9. import org.aspectj.lang.annotation.Aspect;
    10. import org.springframework.beans.factory.annotation.Autowired;
    11. import org.springframework.stereotype.Component;
    12. import javax.servlet.http.HttpServletRequest;
    13. import java.time.LocalDateTime;
    14. import java.util.Arrays;
    15. @Component
    16. @Aspect//切面类
    17. @Slf4j
    18. public class LogAspect {
    19. @Autowired
    20. private HttpServletRequest request;
    21. @Autowired
    22. private OperateLogMapper operateLogMapper;
    23. @Around ( "@annotation(com.itheima.anno.Log)" )
    24. public Object recordLog(ProceedingJoinPoint joinPoint) throws Throwable {
    25. //操作人ID 当前登录员工的ID (从令牌中获取信息)
    26. //获取请求头当中的令牌,解析令牌
    27. String jwt = request.getHeader ( "token" );
    28. Claims claims = JwtUtils.parseJWT ( jwt );
    29. Integer operateUser= (Integer) claims.get ( "id" );
    30. //操作时间
    31. LocalDateTime operateTime = LocalDateTime.now ();
    32. //操作类名
    33. String className = joinPoint.getTarget ().getClass ().getName ();
    34. //操作方法名
    35. String methodName = joinPoint.getSignature ().getName ();
    36. //操作方法参数
    37. Object[] args = joinPoint.getArgs ();
    38. String methodParams = Arrays.toString ( args );
    39. long begin = System.currentTimeMillis ();
    40. //调用原始方法目标执行
    41. Object result = joinPoint.proceed ();
    42. long end = System.currentTimeMillis ();
    43. //方法返回值
    44. String returnValue = JSONObject.toJSONString ( result );
    45. //操作耗时
    46. Long costTime=end-begin;
    47. //记录操作日志
    48. OperateLog operateLog = new OperateLog (null,operateUser,operateTime,className,methodName,methodParams,returnValue,costTime);
    49. operateLogMapper.insert ( operateLog );
    50. log.info ( "AOP记录操作日志:{}",operateLog );
    51. return result;
    52. }
    53. }

    5.数据库表

    1. -- 操作日志表
    2. create table operate_log(
    3. id int unsigned primary key auto_increment comment 'ID',
    4. operate_user int unsigned comment '操作人ID',
    5. operate_time datetime comment '操作时间',
    6. class_name varchar(100) comment '操作的类名',
    7. method_name varchar(100) comment '操作的方法名',
    8. method_params varchar(1000) comment '方法参数',
    9. return_value varchar(2000) comment '返回值',
    10. cost_time bigint comment '方法执行耗时, 单位:ms'
    11. ) comment '操作日志表';

  • 相关阅读:
    C语言深入学习 --- 7.程序的编译
    LintCode 1394 · Goat Latin (字符串处理题)
    定时获取每天早盘数据并自动拼接整理存
    提高测试覆盖率的四大步骤
    RT-Thread Nano系统启动过程研究
    数电实验-----实现74LS153芯片扩展为8选1数据选择器以及应用(Quartus II )
    你好,面试官 | 终于上岸了,你会哪些 JVM 调优参数?呆住了。。。
    java计算机毕业设计基于springboot 在线动漫交流平台
    LeetCode 1796. 字符串中第二大的数字
    跨境业务浏览器选择策略:了解行业领先者的首选
  • 原文地址:https://blog.csdn.net/m0_64703222/article/details/133783449