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

问题描述 投票:44回答:4

我有下面的注释。

my annotation.Java

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

}

some aspect.Java

public class SomeAspect{

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

  //Some logic

}

}

some other.Java

public class SomeOther{

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


}


}

在上面的类中我在@MyAnnotation中传递“ABC”。现在我如何在SomeAspect.java类的procede方法中访问“ABC”值?

谢谢!

java spring spring-aop spring-3 java-ee-7
4个回答
101
投票

你可以从Signature获得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”),如何获得价值?

Class也是AnnotatedElement,所以你可以像Method一样得到它。例如。可以使用获得方法的声明类的注释

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

因为你正在使用弹簧,你可能也想使用spring的AnnotationUtils.findAnnotation(..)。它像spring一样搜索注释。例如。还看着超类和接口方法等

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

14
投票

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

请直接使用注释进行如下尝试:在com.mycompany.MyAnnotation yourAnnotation中添加advice 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可以是有效的变量名,因为params中的MyAnnotation已经指出它应该是哪个注释。这里yourAnnotation仅用于检索注释实例。

如果你想通过更多的参数,你可以试试args()

有关详细信息,请查看其官方doc。对于注释值,您只需搜索@Auditable


3
投票

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

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

要么

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

仅当您的注释在运行时可用时才有效,您已正确声明了该注释。

@Retention(RetentionPolicy.RUNTIME)

0
投票

René的例子让我走了很长的路。还解释了我如何获得ClassLevel Annotations。

但是,如果我之前使用了方法注释“* @ Around(”execution(public *(...))&& @annotation(com.mycompany.MyAnnotation)“)”“那么我只能读取ClassLevel Annotations Values。

我怎么能绕过这个?如何触发类级别的方面注释是在不经过方法执行的情况下设置的?

我想写一个ClassLevel Annotation之类的

@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()上的注释?由于SwaggerConfiguration不知道Application.class(Swagger Stuff它在一个单独的lib中)我不能使用简单的反射

Application.class.getAnnotation(EnableSwaggerApi.class)
© www.soinside.com 2019 - 2024. All rights reserved.