AOP入门第二弹

1 AOP

1.1 AOP相关概念回顾(第一弹)

前面我们介绍过AOP相关概念:参考SpringBoot With IoC,DI, AOP,自动配置

1.1.1 常见通知类型

通知类型解释
@Before前置通知,切入的方法前AOP中声明方法生效
@After后置通知
@Around环绕通知
@AfterReturning返回后通知,方法返回值后AOP中声明方法生效

1.1.2 切入点表达式

在这里插入图片描述

例如:想切入到service的impl包下,任意方法,且被@AuthFill注解声明的方法,请写出切点表达式:

   @Pointcut("execution(* com.sky.service.impl.*.*(..))&& @annotation(com.sky.annotation.AutoFill)")

其中:

特殊字符解释
* com* 表示任意返回值
impl.** 表示任意类
.*(…)* 表示任意方法
.*(…)(…)表示任意类型的参数

1.1.3 AOP的核心概念

名词解释
连接点所有可以进行功能增强的方法
切入点进行了功能增强的方法
通知AOP中所定义的将要被通用的功能
切面切入点+通知
目标对象将要使用AOP中定义方法的对象
切入点表达式指定那些方法是切入点

1.2 AOP使用入门(切入点通过注解声明)

1.2.1 自定义枚举

此处采用分模块开发,将属性名称进行抽离,便于后边各类场景中使用。

/**
 * 数据库操作类型
 */
public enum OperationType {

    /**
     * 更新操作
     */
    UPDATE,

    /**
     * 插入操作
     */
    INSERT

1.2.2 自定义注解

自定义注解中,对 何时执行何种自动填充用value值做限制,便于在切面类定义各种通知生效场景

/**
 * 自定义注解,用于标识某个方法需要进行功能字段自动填充处理
 */
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface AutoFill {
    OperationType value();
}

1.2.3 自定义切面

反射:使用反射获得具体是insert还是update方法,然后进行执行相关对应通知。

/**
 * 自定义切面,实现公共字段自动填充处理逻辑
 */
@Aspect
@Component
@Slf4j
public class AutoFillAspect {
    /**
     * 切入点
     */

    //抽取冗余切入点表达式
    @Pointcut("execution(* com.sky.mapper.*.*(..))&& @annotation(com.sky.annotation.AutoFill)")
    public void authFillPointCut() {
    }

    @Before("authFillPointCut()")
    public void before(JoinPoint joinPoint) {
        log.info("进行了公共字段填充");

        //Signature signature1 = joinPoint.getSignature();//签名对象  为什么 不用Signature获取对象?原因Signature中无getMethod方法,我们需要通过getMethod获取到方法名,从而获取到方法上的注解
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();//方法签名对象,获得方法对象
        //AutoFill autoFill = signature.getMethod().getAnnotation(AutoFill.class);//获取方法上的注解对象
        Method method = signature.getMethod();//获得具体方法
        AutoFill autoFill = method.getAnnotation(AutoFill.class);//获得方法上的注解
        OperationType operationType = autoFill.value(); //获取数据库操作类型

        Object[] args = joinPoint.getArgs();//获取到当前被拦截的方法的参数--实体对象
        if (args == null || args.length == 0){
            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_UPDATE_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){
            //为更新操作的两个字段进行赋值  //TODO
            try {
                Method  setUpdateTime= entity.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_TIME, LocalDateTime.class);
                Method setUpdateUser = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_CREATE_USER, Long.class);
                setUpdateTime.invoke(entity,now);
                setUpdateUser.invoke(entity,currentId);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

1.2.4 切入点上声明注解

自定义注解:中声明操作类型,调用切面类中不同通知。
在这里插入图片描述

    /**
     * 新增分类
     * @param categoryBuild
     */
    @Insert("insert into category (type, name, sort, status, create_time, update_time, create_user, update_user)  " +
            "values (#{type},#{name},#{sort},#{status},#{createTime},#{updateTime},#{createUser},#{updateUser})")
    @AutoFill(value = OperationType.INSERT)
    void insertCategory(Category categoryBuild);
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值