如何从ProceedingJoinPoint获取方法的注释值?


75

我有以下注释。

MyAnnotation.java

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation {

}

SomeAspect.java

public class SomeAspect{

 @Around("execution(public * *(..)) && @annotation(com.mycompany.MyAnnotation)")
    public Object procede(ProceedingJoinPoint call) throws Throwable {

  //Some logic

}

}

SomeOther.java

public class SomeOther{

@MyAnnotation("ABC") 
public String someMethod(String name){


}


}

在上课中,@MyAnnotation中传递了“ ABC ” 。现在如何在SomeAspect.java类的处理方法中访问“ ABC ”值?

谢谢!

Answers:


147

您可以从ProceedingJoinPoint获取签名,如果方法调用,只需将其转换为MethodSignature即可

@Around("execution(public * *(..)) && @annotation(com.mycompany.MyAnnotation)")
public Object procede(ProceedingJoinPoint call) throws Throwable {
    MethodSignature signature = (MethodSignature) call.getSignature();
    Method method = signature.getMethod();

    MyAnnotation myAnnotation = method.getAnnotation(MyAnnotation.class);
}

但是,您应该首先添加一个注释属性。您的示例代码没有一个,例如

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation {

    String value();
}

然后就可以访问它

MyAnnotation myAnnotation = method.getAnnotation(MyAnnotation.class);
String value = myAnnotation.value();

编辑

如果我在班级有@MyAnnotation(“ ABC”),如何获取价值?

AClass也是A AnnotatedElement,因此您可以从A获得相同的方式Method。例如,可以使用以下方法获取方法声明类的注释:

 Method method = ...;
 Class<?> declaringClass = method.getDeclaringClass();
 MyAnnotation myAnnotation = declaringClass.getAnnotation(MyAnnotation.class)

由于您使用的春天,你也可能需要使用Spring的AnnotationUtils.findAnnotation(..)。它像spring一样搜索注释。例如,还要查看超类和接口方法等。

 MyAnnotation foundAnnotation = AnnotationUtils.findAnnotation(method, MyAnnotation.class);

编辑

您可能还会MergedAnnotations对5.2中引入的spring的功能感兴趣。


@ user755806您的注释示例尚未定义属性。我更新了我的答案,但我建议你阅读docs.oracle.com/javase/tutorial/java/annotations
勒内链接

有没有办法在那里更改该注释的值?
艾汉·阿尔斯兰

哇,谢谢你 我整天都在为此苦苦挣扎。谢谢!
弗朗西斯科·哈维尔·巴雷纳

29

实际上,我认为我们可以value用另一种方式获取信息,而不仅仅是从ProceedingJoinPoint获得信息,这肯定需要我们使用reflection

直接使用注释尝试以下操作:com.mycompany.MyAnnotation yourAnnotationadvice params@annotation(yourAnnotation)中添加@Around

@Around("execution(public * *(..)) && @annotation(yourAnnotation)")
public Object procede(ProceedingJoinPoint pjp, com.mycompany.MyAnnotation yourAnnotation) {
    ...
    yourAnnotation.value(); // get your annotation value directly;
    ...
}

com.mycompany.MyAnnotation 在建议参数中就像在

@Around("execution(public * *(..)) && @annotation(com.mycompany.MyAnnotation)")

yourAnnotation可以是有效的变量名,因为MyAnnotation在params中已经指出了它应该是哪个注释。这里yourAnnotation仅用于获取注释实例。

如果您想传递更多的参数,可以尝试args()

有关更多详细信息,请检查其官方文档。对于注释值,您只需搜索即可@Auditable


5
我认为这应该是一个可以接受的答案,因为它更干净,而且记录在案:docs.spring.io/spring/docs/4.3.15.RELEASE/…–
franDayz

我同意(应该接受答案),这绝对是必经之路。公认的答案虽然正确,但却很笨拙。
Paul A. Trzyna,

这将适用于普通的AspectJ还是仅适用于Spring-AOP?
雅各布·布亨斯基

1
@JakubBochenski据我所知,Spring AOP是基于AspectJ构建的,因此基本上,如果Spring AOP可以做到这一点,AspectJ应该以某种方式支持它。但是我自己还没有尝试过; p
Hearen,

1
就像其他用户在上面提到的那样,可接受的答案有效,但是我认为这应该是可接受的答案,因为它很直接且正式记录在此部分:docs.spring.io/spring/docs/4.3.15.RELEASE/…
ame-h

3

这也很好-您可以使用类上的反射来获取批注信息。

Annotation anno = MyClass.class.getAnnotation(MyAnnotation.class);

要么

Annotation anno = MyClass.class.getDeclaredMethod("somethod").getAnnotation(MyAnnotation.class);

仅当注释在运行时可用且正确声明时,此方法才有效。

@Retention(RetentionPolicy.RUNTIME)

您使用哪种注释类,不止一个
JesseBoyd

1

勒内(René)的榜样使我走了很长一段路。也是我如何获得ClassLevel注释的说明。

但是,如果我以前使用过带有“ * @ Around(” execution(public * (..))&& @annotation(com.mycompany.MyAnnotation)“)”

我该如何解决?如果设置了ClassLevel批注而不进行方法执行,如何触发方面?

我想写一个ClassLevel注释

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(value = { ElementType.METHOD, ElementType.TYPE })
@EnableSwagger2
@Import(SwaggerConfiguration.class)
public @interface EnableSwaggerApi {
    String controllerPackage() default "foo.bar.ctrl";
}

它导入有关“ SwaggerConfiguration”的配置,我要在其中接收“ controllerPackage”的值

@Aspect
public class SwaggerConfiguration {

    @Value("${tom.swagger.controller.package:foo.bar.notset}")
    private String  controllerPackage;

    @Value("${tom.swagger.api.version:1.0.0}")
    private String  apiVersion;

    @Value("${spring.application.name:MyApplication}")
    private String  applicationName;

    @Around("execution(public * *(..)) && @annotation(EnableSwaggerApi)")
    public void procede(ProceedingJoinPoint call) throws Throwable {
        MethodSignature signature = (MethodSignature) call.getSignature();
        Method method = signature.getMethod();

        Class<?> declaringClass = method.getDeclaringClass();
        EnableSwaggerApi myAnnotation = declaringClass.getAnnotation(EnableSwaggerApi.class);
        System.err.println("1 -> " + myAnnotation.controllerPackage());  // -> tko.backend.spring.ctrl

        myAnnotation = method.getAnnotation(EnableSwaggerApi.class);
        System.err.println("2 -> " + myAnnotation.controllerPackage()); // -> tko.backend.spring.SOMEOTHERSTUFF


        // THIS WORKS, BUT JUST IF I USE THE @EnableSwaggerApi ON SOME METHOD!
        // NOT ON CLASS

    }

    @Bean
    public Docket swaggerApi() {
        return new Docket(DocumentationType.SWAGGER_2)
                .select()
                .apis(RequestHandlerSelectors.basePackage("controllerPackage"))
                .paths(PathSelectors.any())
                .build()
                .apiInfo(new ApiInfoBuilder().version(apiVersion).title(applicationName).description("Documentation " + applicationName + " API v" + apiVersion)
                        .build());
    }

    @Bean
    public CorsFilter corsFilter() {
        final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        final CorsConfiguration config = new CorsConfiguration();
        config.setAllowCredentials(true);
        config.addAllowedOrigin("*");
        config.addAllowedHeader("*");
        config.addAllowedMethod("*");
        source.registerCorsConfiguration("/v2/api-docs", config);
        return new CorsFilter(source);
    }
}





@EnableSwaggerApi(controllerPackage="tko.backend.spring.ctrl")
public class Application extends SpringBootServletInitializer {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }

    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
        return application.sources(Application.class, Initializer.class);
    }


    @Bean
    @EnableSwaggerApi(controllerPackage="tko.backend.spring.SOMEOTHERSTUFF")
    public String initSwagger() {
        return "some dummy";
    }

}

如何摆脱initSwagger()上的注释?由于Application.class尚不为SwaggerConfiguration(扬鞭东西它是在一个单独的IIb)的我不能使用像简单反射

Application.class.getAnnotation(EnableSwaggerApi.class)

0

使用AspectJ / AOP查找方法注释和类级别注释的工作代码

   @Around("execution(* com.first.test.controller..*(..)))")
    public Object profileAllMethods(ProceedingJoinPoint proceedingJoinPoint) throws Throwable
    {
        MethodSignature methodSignature = (MethodSignature) proceedingJoinPoint.getSignature();

        java.lang.reflect.Method method = methodSignature.getMethod();

  Annotation []methodAnnotations =  method.getDeclaredAnnotations();
        System.out.println("==============="+methodAnnotations[0].toString());

        Annotation []classAnnotations = proceedingJoinPoint.getTarget().getClass().getAnnotations();

        System.out.println("===Class Annotation : "+classAnnotations[1].toString());
       Object result = proceedingJoinPoint.proceed();
        return result;
    }
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.