如何简化公共字段
简化公共字段我们需要了解AOP相关的知识
通知类型
前置通知
环绕通知
后置通知
抛出异常通知
注意事项
用@Order注解控制执行顺序
两种切入点表达式
先定义一个注解 再在要添加事务的方法上添加自己写的注解 就可以在通知类型的注解后匹配到要添加事务的方法了
环绕通知获取连接点的信息
@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;
}
其他通知获取连接点信息
学习使用事务
事务的作用
当程序运行出现异常(出现运行时异常) 会使程序回滚 使程序一起执行
用@Transactional注解开启事务(在Spring框架中集成好了 直接调用)
使出现所有异常都会回滚
需要在yml配置文件中添加如下配置
#spring事务管理日志
logging:
level:
org.springframework.jdbc.support.JdbcTransactionManager: debug
使日志始终输出
@Service
public class DeptLogServiceImpl implements DeptLogService {
@Autowired
private DeptLogMapper deptLogMapper;
@Transactional(propagation = Propagation.REQUIRES_NEW)
// 开启新的事务
@Override
public void insert(DeptLog deptLog) {
deptLogMapper.insert(deptLog);
}
}
正常情况下finally 中的内容不会写入数据库
但是加了(propagation = Propagation.REQUIRES_NEW) 就会将日志写到数据库 因为是开启了一个新的事务不会受其他的事务影响
@Override
@Transactional(rollbackFor = Exception.class)
public void delete(Integer id) {
try {
// 删除部门
deptMapper.deleteById(id);
// 删除部门关系表数据
empMapper.deleteByDeptId(id);
}finally {
DeptLog deptLog = new DeptLog();
deptLog.setCreateTime(LocalDateTime.now());
deptLog.setDescription("执行了解散部门的操作,此次解散的是"+id+"号部门");
deptLogMapper.insert(deptLog);
}
}
接下来我们完成公共字段的简化
创建自定义注解类
/**
* @Author: Sakura
* @Date: 2024/8/17 17:37
* @Version: v1.0.0
* @Description: TODO
* 自定义注解,用于标识需要自动填充的公共字段
**/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface AutoFill {
// 数据库操作类型
OperationType value();
}
创建自定义注解切面类
/**
* @Author: Sakura
* @Date: 2024/8/17 18:43
* @Version: v1.0.0
* @Description: TODO
* 自定义注解切面类 用于实现公共字段的自动填充
**/
@Aspect
@Component
@Slf4j
public class AutoFillAspect {
/**
* 切入点
*/
@Pointcut("execution(* com.sky.mapper.*.*(..)) && @annotation(com.sky.annotaion.AutoFill)")
public void autoFillPointCut() {}
@Before("autoFillPointCut()")
public void autoFill(JoinPoint joinPoint){
log.info("开始进行公共字段自动填充");
// 获取到拦截到的方法上的操作类型
MethodSignature signature = (MethodSignature) joinPoint.getSignature();// 获取到方法签名
AutoFill autoFill = signature.getMethod().getAnnotation(AutoFill.class);// 获取到方法上的注解
OperationType operationType = autoFill.value();// 获取到注解上的操作类型
// 获取到拦截到的方法的参数
Object[] args = joinPoint.getArgs();
if (args.length == 0 || args[0] == null){
return;
}
Object entity = args[0];
// 准备填充的数据
LocalDateTime now = LocalDateTime.now();
Long currentId = BaseContext.getCurrentId();
// 根据不同的操作类型,将对应的数据填充到对应的参数中
if (operationType == OperationType.INSERT){
// 为四个公共字段赋值
try {
Method setCreateTime = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_CREATE_TIME, LocalDateTime.class);
Method setCreateUser = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_CREATE_USER, Long.class);
Method setUpdateTime = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_TIME, LocalDateTime.class);
Method setUpdateUser = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_CREATE_USER, Long.class);
// 通过反射 为四个公共字段赋值
setCreateTime.invoke(entity,now);
setCreateUser.invoke(entity,currentId);
setUpdateTime.invoke(entity,now);
setUpdateUser.invoke(entity,currentId);
} catch (Exception e) {
e.printStackTrace();
}
}else if (operationType == OperationType.UPDATE){
// 为两个公共字段赋值
try {
Method setUpdateTime = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_TIME, LocalDateTime.class);
Method setUpdateUser = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_USER, Long.class);
// 通过反射 为两个公共字段赋值
setUpdateTime.invoke(entity,now);
setUpdateUser.invoke(entity,currentId);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
在Mapper的方法上添加@AutoFill注解实现公共字段的填充
使用SQL语句获取主键值