Java 如何从 ProceedingJoinPoint 获取方法的注释值?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/21275819/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to get a method's annotation value from a ProceedingJoinPoint?
提问by user755806
I have below annotation.
我有以下注释。
MyAnnotation.java
我的注解
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation {
}
SomeAspect.java
一些方面.java
public class SomeAspect{
@Around("execution(public * *(..)) && @annotation(com.mycompany.MyAnnotation)")
public Object procede(ProceedingJoinPoint call) throws Throwable {
//Some logic
}
}
SomeOther.java
SomeOther.java
public class SomeOther{
@MyAnnotation("ABC")
public String someMethod(String name){
}
}
In above class am passing "ABC" with in @MyAnnotation. Now how can i access "ABC" value in procedemethod of SomeAspect.javaclass?
在上面的课程中,我在@MyAnnotation 中传递了“ ABC” 。现在如何在SomeAspect.java类的procede方法中访问“ ABC”值?
Thanks!
谢谢!
采纳答案by René Link
You can get the Signaturefrom a ProceedingJoinPointand in case of a method invocation just cast it to a MethodSignature.
您可以从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);
}
But you should first add an annotation attribute. Your example code doesn't have one, e.g.
但是您应该首先添加一个注释属性。您的示例代码没有,例如
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation {
String value();
}
Then you can access it
然后就可以访问了
MyAnnotation myAnnotation = method.getAnnotation(MyAnnotation.class);
String value = myAnnotation.value();
EDIT
编辑
How to get value if I have @MyAnnotation("ABC") at class level ?
如果我在类级别有 @MyAnnotation("ABC") ,如何获得价值?
A Class
is also an AnnotatedElement
, so you can get it the same way as from a Method
. E.g. An annotation of the method's declaring class can be obtained using
AClass
也是 an AnnotatedElement
,因此您可以通过与从 a 相同的方式获取它Method
。例如,可以使用以下方法获得方法声明类的注释
Method method = ...;
Class<?> declaringClass = method.getDeclaringClass();
MyAnnotation myAnnotation = declaringClass.getAnnotation(MyAnnotation.class)
Since you are using spring you might also want to use spring's AnnotationUtils.findAnnotation(..)
. It searches for an annotation as spring does. E.g. also looking at superclass and interface methods, etc.
由于您使用的是 spring,您可能还想使用 spring 的AnnotationUtils.findAnnotation(..)
. 它像 spring 一样搜索注释。例如,还要查看超类和接口方法等。
MyAnnotation foundAnnotation = AnnotationUtils.findAnnotation(method, MyAnnotation.class);
EDIT
编辑
You might also be interessted in the capabilities of spring's MergedAnnotations
which was introduced in 5.2.
您可能还MergedAnnotations
对 5.2 中引入的 spring 的功能感兴趣。
回答by Martin Frey
This works as well - You can fetch annotation information using reflection on the class.
这也有效 - 您可以使用类上的反射来获取注释信息。
Annotation anno = MyClass.class.getAnnotation(MyAnnotation.class);
Or
或者
Annotation anno = MyClass.class.getDeclaredMethod("somethod").getAnnotation(MyAnnotation.class);
This works only if your annotation is available at runtime, which you have declared correctly.
仅当您的注释在运行时可用且您已正确声明时,这才有效。
@Retention(RetentionPolicy.RUNTIME)
回答by Hearen
Actually I think we can get the value
in another way round instead of just from ProceedingJoinPoint, which will definitely require us to make use of reflection
.
实际上,我认为我们可以通过value
另一种方式获得 ,而不仅仅是从ProceedingJoinPoint 获得,这肯定需要我们使用reflection
.
Have a try as follows using annotation directly: add com.mycompany.MyAnnotation yourAnnotation
in your advice params
and @annotation(yourAnnotation)
in @Around
.
直接使用注解试试如下: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
in advice params just work as that in
com.mycompany.MyAnnotation
在建议参数中就像在
@Around("execution(public * *(..)) && @annotation(com.mycompany.MyAnnotation)")
yourAnnotation
can be valid variable name since MyAnnotation
in params already points out which annotation it should be. Here yourAnnotation
is used to retrieve the annotation instance only.
yourAnnotation
可以是有效的变量名,因为MyAnnotation
在 params 中已经指出它应该是哪个注释。这里yourAnnotation
仅用于检索注释实例。
If you want to pass more params you can try args()
.
如果你想传递更多参数,你可以尝试args()
.
For more details, do please check its official doc. For Annotation value, you can just search @Auditable
.
有关更多详细信息,请查看其官方文档。对于 Annotation 值,您只需搜索@Auditable
.
回答by Tom K.
René'sexample is taking me a long way. Also the explanation how I get ClassLevel Annotations.
René 的例子让我受益匪浅。还解释了我如何获得 ClassLevel Annotations。
But then I can only read ClassLevel Annotations Values if I have previously used a method annotation with "*@Around("execution(public * (..)) && @annotation(com.mycompany.MyAnnotation)")""
但后来我只能读ClassLevel标注值,如果我以前使用的方法与标注“* @大约(”执行(公* (..))&& @annotation(com.mycompany.MyAnnotation)“)”“
How can I get around this? How can I trigger an Aspect if a ClassLevel Annotation is set without going through a Method Execution?
我怎样才能解决这个问题?如果在不通过方法执行的情况下设置了 ClassLevel 注释,如何触发方面?
I want to write a ClassLevel Annotation like
我想写一个 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";
}
It's importing the Configuration about "SwaggerConfiguration" where I want to receive the value of "controllerPackage"
它正在导入有关“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";
}
}
How can I can rid of the annotation on initSwagger()? Since the Application.classis not known to SwaggerConfiguration(Swagger Stuff it's in a separate lib) I can't use simple reflection like
我怎样才能摆脱initSwagger()上的注释?由于Application.class不为SwaggerConfiguration 所知(Swagger Stuff 它在一个单独的库中)我不能使用简单的反射
Application.class.getAnnotation(EnableSwaggerApi.class)
回答by Rajeev Rathor
Find working code for Method Annotation and class level annotation using AspectJ/AOP
使用 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;
}