AOP编程

W aop

aop底层可以理解为动态代理技术,无侵入式给方法增加功能。在aop类中必须加上@Aspect注解

aop主要包含2个方面

1.切入点表达式

有两种方法定义切入点表达式,各部分含义为

返回值  包名 类名 方法名 方法参数  

通过方法定义或者直接在通知注解上定义,

//切入点表达式1
@Pointcut("execution(* com.sky.mapper.*.*(..)) && @annotation(com.sky.Annotion.AutoFill)")
    public void pointCut(){}
//切入点表达式2
@Around("execution(* com.itheima.service.*.*(..))") 

//通知注解
   
@Before("pointCut()")
2.通知
  • @Around:环绕通知,此注解标注的通知方法在目标方法前、后都被执行

  • @Before:前置通知,此注解标注的通知方法在目标方法前被执行@After :后置通知,此注解标注的通知方法在目标方法后被执行,无论是否有异常都会执行

  • @AfterReturning : 返回后通知,此注解标注的通知方法在目标方法后被执行,有异常不会执行

  • @AfterThrowing : 异常后通知,此注解标注的通知方法发生异常后执行

JoinPoint到底是是个什么玩意?

JoinPoint封装了代理对象,或者叫连接点@Around中连接点只能是ProceedingJoinPoint

其他通知类型为JoinPoint,ProceedingJoinPoint是JoinPoint的子类。

通过连接点可以获得方法的各种信息。

  1. Signature getSignature();    获取封装了署名信息的对象,在该对象中可以获取到目标方法名,所属类的Class等信息
  2. Object[] getArgs();    获取传入目标方法的参数对象
  3. Object getTarget();    获取被代理的对象
  4. Object getThis();    获取代理对象

//返回的是代理对象
        Object target = joinPoint.getTarget();
        log.info("target:{}",target);
        Signature signature1 = joinPoint.getSignature();
        log.info("singnature:{}",signature1);


        MethodSignature signature = (MethodSignature)joinPoint.getSignature();
        log.info("MethodSignature:{}",signature);
aop实例:自动添加公共字段,即使用代理调用相关方法,自动完成封装
package com.sky.Aspect;

import com.sky.Annotion.AutoFill;
import com.sky.constant.AutoFillConstant;
import com.sky.context.BaseContext;
import com.sky.enumeration.OperationType;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.time.LocalDateTime;

@Aspect
@Component
@Slf4j
public class AutoFillAdpect {
    /*
    切入点表达式
     */
    //返回值,包名,类名,方法名,参数名
    @Pointcut("execution(* com.sky.mapper.*.*(..)) && @annotation(com.sky.Annotion.AutoFill)")
    public void pointCut(){}


    /*
    通知:前置通知,为公共字段赋值
     */
    @Before("pointCut()")
    //参数为拦截的方法
    public void autoFill(JoinPoint joinPoint)  {
        log.info("开始公共字段填充");
        //获取数据库存操作对象(向下转型

        //返回的是代理对象
        Object target = joinPoint.getTarget();
        log.info("target:{}",target);
        Signature signature1 = joinPoint.getSignature();
        log.info("singnature:{}",signature1);


        MethodSignature signature = (MethodSignature)joinPoint.getSignature();
        log.info("MethodSignature:{}",signature);
        AutoFill autoFill = signature.getMethod().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 createtime = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_CREATE_TIME, LocalDateTime.class);
                Method updatetime = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_TIME, LocalDateTime.class);
                Method createuser = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_CREATE_USER, Long.class);
                Method updateuser = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_USER, Long.class);

                //反射赋值
                createtime.invoke(entity,now);
                updatetime.invoke(entity,now);
                createuser.invoke(entity,BaseContext.getCurrentId());
                updateuser.invoke(entity,BaseContext.getCurrentId());

            } catch (Exception e) {
                e.printStackTrace();
            }
        }else {
            //只需要赋值两个公共字段
            try {
                Method updatetime = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_TIME, LocalDateTime.class);
                Method updateuser = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_USER, Long.class);
                //反射赋值
                updatetime.invoke(entity,now);
                updateuser.invoke(entity,BaseContext.getCurrentId());

            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}

  • 9
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值