切面编程Spring-AOP

177 阅读1分钟

几个稍微复杂的切入点表达式

1、某个包下的所有类,且排除掉其中的一个类

tips: tech.cxcool.test.controller包下除了AttachController之外的所有Controller都会被该切面拦截到

@Pointcut(value = "execution(public * tech.cxcool.test.controller.*.*(..))&&!execution(public * tech.cxcool.test.controller.AttachController.*(..))")

2、既要包含类上的注解,也要包含类内方法上的注解

tips: @AddBusiId在类上使用或者在方法上使用都会被切面拦截到@annotation(tech.cxcool.test.common.annotation.AddBusiId)||@within(tech.cxcool.test.common.annotation.AddBusiId)

AOP+自定义注解

实战1

tips: 使用spring中的AOP,完成向返回值中添加busiId的功能,注意,这个busiId是个定值,是从注解@AddBusiId里面的属性值中获取到的。

highlights:

  • 使用spring中的工具类AnnotationUtils对注解进行处理,用于获取标注在“方法”或者“类”上的注解,并获取相应的注解的属性值。
  • 如果存在方法级别的注解,会优先于类级别的注解进行处理。

注解

public @interface AddBusiId {

    String   value() default "";

}

切面

/**
 * author: panhe
 * create_time: 2021/7/6 19:10
 * description:
 * 切面类 :向接口返回对象中追加busiId字段,值为注解中带入的value值
 *
 */
@Component
@Aspect
public class ResAddBusiIdAop {

    @Pointcut("@annotation(tech.cxcool.test.common.annotation.AddBusiId)||@within(tech.cxcool.test.common.annotation.AddBusiId)")
    public void point1() {}

    @Around("point1()")
    public Object test(ProceedingJoinPoint pjp) throws Throwable {
//        System.out.println("进入切面....");
        Object obj = pjp.proceed();
        if(obj instanceof ResponseEntity){
            ResponseEntity res  =  (ResponseEntity)obj ;
            ResObject  res2= (ResObject)res.getBody();
            String busiId = getBusiId(pjp);
            ResObjectExt resObjectExt =  new ResObjectExt(res2,busiId);
            return  new ResponseEntity(resObjectExt, HttpStatus.OK);
        }
        return  obj  ;
    }


    //-----------------------私有方法----------------------
    /**
     * 获取指定注解的属性值
     * @param pjp
     * @return
     */
    private  String  getBusiId(ProceedingJoinPoint pjp) throws NoSuchMethodException {
//        System.out.println("获取方法上的注解--------------->");
        Class<?> targetCls=pjp.getTarget().getClass();
        MethodSignature ms=(MethodSignature)pjp.getSignature();
        Method targetMethod=
                targetCls.getDeclaredMethod(
                        ms.getName(),
                        ms.getParameterTypes());
        Annotation methodAnno =  AnnotationUtils.findAnnotation(targetMethod,AddBusiId.class);
        if(methodAnno !=null){
            Object val   =  AnnotationUtils.getValue(methodAnno);
            return   val == null ? "":(String)val;
        }
//        System.out.println("获取类上的注解----------------->");
        Annotation classAnno  =  AnnotationUtils.findAnnotation(pjp.getTarget().getClass(),AddBusiId.class);
        Object val   =  AnnotationUtils.getValue(classAnno);
        return   val == null ? "":(String)val;
    }
}