You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Spring AOP中拦截方法上的元注解(注解的注解)

Spring AOP 方法上元注解拦截的正确切点表达式

已经实现了Spring AOP对类上元注解的拦截,但现在需要拦截方法上的元注解,现有切面表达式仅能作用于类,尝试多种写法都报“切面表达式无法解析”错误,以下是可行的解决方案。


原注解与切面代码

MetaAnnotation元注解

package de.scrum_master.app;

import static java.lang.annotation.ElementType.*;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

import java.lang.annotation.Retention;
import java.lang.annotation.Target;

@Retention(RUNTIME)
@Target({ TYPE })
public @interface MetaAnnotation {}

MyAnnotation注解(标注了元注解)

package de.scrum_master.app;

import static java.lang.annotation.ElementType.*;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

import java.lang.annotation.Retention;
import java.lang.annotation.Target;

@Retention(RUNTIME)
@Target({ TYPE })
@MetaAnnotation
public @interface MyAnnotation {}

原切面类

package de.scrum_master.aspect;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;

@Aspect
public class MetaAnnotationInterceptor {
  @Before(
    "execution(* *(..)) && (" +
      "within(@de.scrum_master.app.MetaAnnotation *) || " +
      "within(@(@de.scrum_master.app.MetaAnnotation *) *)" +
    ")"
  )
  public void myAdvice(JoinPoint thisJoinPoint){
    System.out.println(thisJoinPoint);
  }
}

解决方案

第一步:修改注解的Target范围

原代码中两个注解的@Target仅设置了TYPE,只能标注在类上。要支持方法级标注,需给注解添加METHOD类型:

修改后的MetaAnnotation

package de.scrum_master.app;

import static java.lang.annotation.ElementType.*;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

import java.lang.annotation.Retention;
import java.lang.annotation.Target;

@Retention(RUNTIME)
@Target({ TYPE, METHOD }) // 添加METHOD支持
public @interface MetaAnnotation {}

修改后的MyAnnotation

package de.scrum_master.app;

import static java.lang.annotation.ElementType.*;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

import java.lang.annotation.Retention;
import java.lang.annotation.Target;

@Retention(RUNTIME)
@Target({ TYPE, METHOD }) // 添加METHOD支持
@MetaAnnotation
public @interface MyAnnotation {}

第二步:编写支持方法上元注解的切点表达式

正确的表达式需要覆盖四种拦截场景:类直接标注元注解、类标注的注解被元注解修饰、方法直接标注元注解、方法标注的注解被元注解修饰。

修改后的切面类代码:

package de.scrum_master.aspect;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;

@Aspect
public class MetaAnnotationInterceptor {
  @Before(
    "execution(* *(..)) && (" +
      // 拦截类直接标注MetaAnnotation的所有方法
      "within(@de.scrum_master.app.MetaAnnotation *) || " +
      // 拦截类标注了被MetaAnnotation修饰的注解的所有方法
      "within(@(@de.scrum_master.app.MetaAnnotation *) *) || " +
      // 拦截方法直接标注MetaAnnotation的情况
      "@annotation(de.scrum_master.app.MetaAnnotation) || " +
      // 拦截方法标注了被MetaAnnotation修饰的注解的情况
      "@annotation(@de.scrum_master.app.MetaAnnotation *)" +
    ")"
  )
  public void myAdvice(JoinPoint thisJoinPoint){
    System.out.println(thisJoinPoint);
  }
}

内容的提问来源于stack exchange,提问作者White

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.25 12:28:25