Aop自定义注解

AOP

在这里插入图片描述

  • Aspect(切面): Aspect 声明类似于 Java 中的类声明,在 Aspect 中会包含着一些 Pointcut 以及相应的 Advice。
  • Joint point(连接点):表示在程序中明确定义的点,典型的包括方法调用,对类成员的访问以及异常处理程序块的执行等等,它自身还可以嵌套其它 joint point。
  • Pointcut(切点):表示一组 joint point,这些 joint point 或是通过逻辑关系组合起来,或是通过通配、正则表达式等方式集中起来,它定义了相应的 Advice 将要发生的地方。
  • Advice(增强):Advice 定义了在 Pointcut 里面定义的程序点具体要做的操作,它通过 before、after 和 around 来区别是在每个 joint point 之前、之后还是代替执行的代码。
  • Target(目标对象):织入 Advice 的目标对象.。
  • Weaving(织入):将 Aspect 和其他对象连接起来, 并创建 Adviced object 的过程

Piontcut切点

execution表达式(满足某一匹配模式的的所有目标类方法连接点)

execution(<修饰符>? <返回类型> <类路径>?<方法名>(<参数列表>) <异常模式>? )

execution(modifiers-pattern? ret-type-pattern declaring-type-pattern?name-pattern(param-pattern) throws-pattern?)

  • modifiers-pattern:方法的可见性,如public,protected;
  • ret-type-pattern:方法的返回值类型,如int,void等;
  • declaring-type-pattern:方法所在类的全路径名,如com.spring.Aspect;
  • name-pattern:方法名类型,如buisinessService();
  • param-pattern:方法的参数类型,如java.lang.String;
  • throws-pattern:方法抛出的异常类型,如java.lang.Exception;

@annotation (标注了特定注解的目标方法连接点上)

例:

@Around("@annotation(com.cocosa.hrssc.tenant.api.Annotation.NoRepeated)")

Advice(增强)

处理时机(参数为Pointcut)

  • @Before:前置增强:目标方法执行之前先调用增强方法

  • @After:后置增强:目标方法执行之后调用增强方法

  • @AfterReturning:返回增强:目标方法执行return之后返回结果之前调用增强方法,如果出异常则不执行

  • @AfterThrowing:异常增强:目标方法执行产生异常调用增强方法

  • @Around:环绕增强,包含前面四种增强

处理内容

处理内容为具体方法,参数为JoinPointProceedingJoinPoint。Proceedingjoinpoint 继承了 JoinPoint 。是在JoinPoint的基础上暴露出 proceed 这个方法。

Example(重复请求)

自定义注解

@Target(value = {ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
public @interface NoRepeated {

    String key() default "";

    //过期时间,使用本地缓存可以忽略,如果使用redis做缓存就需要
    int expire() default 5;
}

切面

@Order(1)//切面执行顺序,数字越小优先级越高,默认为字典顺序
@Aspect
@Component
public class NoRepeatedMethodInterceptor {

    /**
     * 本地缓存 expire: 20s
     */
    private static final Cache<String, Object> CACHE = CacheBuilder.newBuilder().maximumSize(1000).expireAfterWrite(20, TimeUnit.SECONDS).build();
	//环绕增强 NoRepeated注解 && 以Controller结尾的类所有方法
    @Around("@annotation(com.cocosa.hrssc.tenant.api.Annotation.NoRepeated) && execution(* *..*Controller.*(..)))")
    public Object interceptor(ProceedingJoinPoint joinPoint) {
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
        NoRepeated noRepeated = method.getAnnotation(NoRepeated.class);
        String key = getKey(noRepeated.key(), joinPoint.getArgs());
        if (!StringUtils.isEmpty(key)) {
            if (CACHE.getIfPresent(key) != null) {
                //自定义全局异常处理
                throw new BusinessException("请勿重复请求!");
            }
            CACHE.put(key, key);
        }
        try {
            //执行目标对象方法
            return joinPoint.proceed();
        } catch (Throwable throwable) {
            //自定义全局异常处理
            throw new BusinessException("服务器异常");
        } finally {

        }
    }

    private String getKey(String keyExpress, Object[] args) {
        for (int i = 0; i < args.length; i++) {
            keyExpress = keyExpress.replace("arg[" + i + "]", MD5.create().digestHex(JSON.toJSONString(args[i])));
        }
        return keyExpress;
    }
}

注解补充

@Target 注解

指明了修饰的这个注解的使用范围,即被描述的注解可以用在哪里。

ElementType的取值包含以下几种:

  • TYPE:类,接口或者枚举
  • FIELD:域,包含枚举常量
  • METHOD:方法
  • PARAMETER:参数
  • CONSTRUCTOR:构造方法
  • LOCAL_VARIABLE:局部变量
  • ANNOTATION_TYPE:注解类型
  • PACKAGE:包

@Retention 注解

指明修饰的注解的生存周期,即会保留到哪个阶段。

RetentionPolicy的取值包含以下三种:

  • SOURCE:源码级别保留,编译后即丢弃。
  • CLASS:编译级别保留,编译后的class文件中存在,在jvm运行时丢弃,这是默认值。
  • RUNTIME: 运行级别保留,编译后的class文件中存在,在jvm运行时保留,可以被反射调用。

@Documented 注解

指明修饰的注解,可以被例如javadoc此类的工具文档化,只负责标记,没有成员取值。

@Inherited注解

允许子类继承父类中的注解。

ME: 运行级别保留,编译后的class文件中存在,在jvm运行时保留,可以被反射调用。

@Documented 注解

指明修饰的注解,可以被例如javadoc此类的工具文档化,只负责标记,没有成员取值。

@Inherited注解

允许子类继承父类中的注解。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值