<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
以给公共字段注入值为例
private LocalDateTime createTime;
private LocalDateTime updateTime;
private Long createUser;
private Long updateUser;
/**
* 数据库操作类型
*/
public enum OperationType {
/**
* 更新操作
*/
UPDATE,
/**
* 插入操作
*/
INSERT
}
自定义注解 @AutoFill
/**
* 自定义注解,用于标识某个方法需要进行功能字段自动填充
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface AutoFill {
//数据库操作类型:UPDATE、INSERT
OperationType values();
}
/**
* 自定义切片,实现公共字段字段填充
*/
@Aspect
@Component
@Slf4j
public class AutoFillAspect {
/**
* 切入点
* @Pointcut注解表示切入点的表达式有多种,最常用的是两种,execution表达式和@annotation注解;
* execution(* com.sky.mapper.*.*(..)) 表示 com.sky.mapper包下所有类的所有方法
* @annotation(com.sky.annotation.AutoFill) 表示 com.sky.annotion包下的AutoFill注解
*/
@Pointcut("execution(* com.sky.mapper.*.*(..)) && @annotation(com.sky.annotation.AutoFill)")
public void autoFillPointCut(){}
/**
* 前置通知,在通知中进行公共字段赋值
* 可以joinpoint中得到命中方法的相关信息,利用这些信息可以做一些额外的业务操作;
* @Before("autoFillPointCut()") 表示接入点为autoFillPointCut()的切入点
*/
@Before("autoFillPointCut()")
public void autoFill(JoinPoint joinPoint){
log.info("开始公共字段自动填充...");
//获取到当前被拦截的方法上的数据库操作类型
MethodSignature signature=(MethodSignature) joinPoint.getSignature();//对象方法签名
AutoFill autoFill = signature.getMethod().getAnnotation(AutoFill.class);//获得方法上的注解对象
OperationType values = autoFill.values();//获得数据库操作对象
//获取到当前被拦截的方法的参数--实体对象
Object[] args = joinPoint.getArgs();
if(args==null||args.length==0) {return;}
Object entity = args[0];
//准备赋值的数据
LocalDateTime localDateTime = LocalDateTime.now();
Long currentId = BaseContext.getCurrentId();
//根据当前不同的操作类型,为对应属性通过反射来赋值
if(values==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_UPDATE_USER, Long.class);
setCreateTime.invoke(entity,localDateTime);
setCreateUser.invoke(entity,currentId);
setUpdateTime.invoke(entity,localDateTime);
setUpdateUser.invoke(entity,currentId);
} catch (Exception e) {
e.printStackTrace();
}
}else if(values==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,localDateTime);
setUpdateUser.invoke(entity,currentId);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
表达式法:访问修饰符 返回值 包名.包名…类名.方法(参数列表)
//1. 表示匹配所有com.fanfu包以及子包下的所有类中以add开头的方法,返回值、参数不限;
@Pointcut("execution(* com.fanfu..*.*.add*(..))")
//2. 表示匹配所有com.fanfu包以及子包下的所有类中以add开头,参数类型是String的方法,返回值不限;
@Pointcut("execution(* com.fanfu..*.*.add*(String))")
//3. 表示匹配com.fanfu包下任意类、任意方法、任意参数;
@Pointcut("execution(* com.fanfu..*.*.*(String))")
注解语法:@annotation(自定义的注解)
//表示有@AutoFill注解的方法
@Pointcut("@annotation(com.sky.annotation.AutoFill)")