场景

利用AOP实现Mapper层操纵数据库时的公共字段填充,例如: -创建时间 -更新时间 -创建用户 -更新用户

代码

创建注解辅助AOP精准定位切入点,OperateType为区别AOP实际增强业务。

public enum OperateType {

    INSERT,

    UPDATE,

    USERID;

}

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface AutoFill {

    /**
     * 数据库操作类型,INSERT插入操作,UPDATE更新操作
     */
    OperateType[] value();

}

创建切面类

// Aspect注解标识
@Aspect
@Component
public class AutoFillAspect {

    // 切点定义       任何返回值                           任何类的任何方法(方法的参数任意)      必须有`AutoFill`注解
    @Pointcut("execution(* com.bilubi.reggie.reggie.mapper.*.*(..)) && @annotation(com.bilubi.reggie.reggie.annotation.AutoFill)")
    public void autoFillPointcut() {
    }

    // 前置通知
    @Before("autoFillPointcut()")
    public void autoFill(JoinPoint joinPoint) {

        //获取方法签名对象
        MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
        //获取注解对象
        AutoFill autoFill = methodSignature.getMethod().getAnnotation(AutoFill.class);
        //获取数据库操作类型
        OperateType[] operateType = autoFill.value();

        //获取拦截方法实体类对象参数
        Object[] args = joinPoint.getArgs();
        if (args == null || args.length == 0) {
            return;
        }

        Object entity = args[0];

        //获取参数类型
        Class<?> entityClass = entity.getClass();

        //获取填充数据
        Long createUserId = BaseContext.getValue();// 当前用户名
        Date now = new Date();// 当前时间
        log.info("时间:{}", now.toString());

        for (OperateType operateType_ : operateType) {
            //为插入操作填充数据
            if (operateType_ == OperateType.INSERT) {
                try {
                    if (List.class.isAssignableFrom(entityClass)) {
                        for (Object object : (List<?>) entity) {
                            Method setCreateUser = object.getClass()
                                    .getMethod("setCreateUser", Long.class);
                            Method setUpdateUser = object.getClass()
                                    .getMethod("setUpdateUser", Long.class);
                            Method setCreateTime = object.getClass()
                                    .getMethod("setCreateTime", Date.class);
                            Method setUpdateTime = object.getClass()
                                    .getMethod("setUpdateTime", Date.class);

                            setCreateUser.invoke(object, createUserId);
                            setUpdateUser.invoke(object, createUserId);
                            setCreateTime.invoke(object, now);
                            setUpdateTime.invoke(object, now);
                        }
                    }
                    else {
                        Method setCreateUser = entity.getClass()
                                .getMethod("setCreateUser", Long.class);
                        Method setUpdateUser = entity.getClass()
                                .getMethod("setUpdateUser", Long.class);
                        Method setCreateTime = entity.getClass()
                                .getMethod("setCreateTime", Date.class);
                        Method setUpdateTime = entity.getClass()
                                .getMethod("setUpdateTime", Date.class);

                        setCreateUser.invoke(entity, createUserId);
                        setUpdateUser.invoke(entity, createUserId);
                        setCreateTime.invoke(entity, now);
                        setUpdateTime.invoke(entity, now);
                    }
                } catch (Exception ex) {
                    throw new RuntimeException();
                }
            }

            //为更新操作填充数据
            if (operateType_ == OperateType.UPDATE) {
                try {
                    if (List.class.isAssignableFrom(entityClass)) {
                        for (Object object : (List<?>) entity) {
                            Method setUpdateUser = object.getClass()
                                    .getMethod("setUpdateUser", Long.class);
                            Method setUpdateTime = object.getClass()
                                    .getMethod("setUpdateTime", Date.class);

                            setUpdateUser.invoke(object, createUserId);
                            setUpdateTime.invoke(object, now);
                        }
                    }
                    else {
                        Method setUpdateUser = entity.getClass()
                                .getMethod("setUpdateUser", Long.class);
                        Method setUpdateTime = entity.getClass()
                                .getMethod("setUpdateTime", Date.class);

                        setUpdateUser.invoke(entity, createUserId);
                        setUpdateTime.invoke(entity, now);
                    }
                } catch (Exception ex) {
                    throw new RuntimeException();
                }
            }

            //为user对象填充uesrID
            if (operateType_ == OperateType.USERID){
                try {
                    Method method = entityClass.getMethod("setUserId", Long.class);
                    method.invoke(entity, createUserId);
                }
                catch (Exception ex) {
                    throw new RuntimeException();
                }
            }
        }
    }
}

AOP切面类的其他通知类型

@Aspect
@Component
public class AopAdvice {

    @Pointcut("execution (* com.shangguan.aop.controller.*.*(..))")
    public void test() {

    }

    @Before("test()")
    public void beforeAdvice() {
        System.out.println("beforeAdvice...");
    }

    @After("test()")
    public void afterAdvice() {
        System.out.println("afterAdvice...");
    }

    @Around("test()")
    public void aroundAdvice(ProceedingJoinPoint proceedingJoinPoint) {
        System.out.println("before");
        try {
            proceedingJoinPoint.proceed();
        } catch (Throwable t) {
            t.printStackTrace();
        }
        System.out.println("after");
    }

}