我有下面的注释。
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation {
}
public class SomeAspect{
@Around("execution(public * *(..)) && @annotation(com.mycompany.MyAnnotation)")
public Object procede(ProceedingJoinPoint call) throws Throwable {
//Some logic
}
}
public class SomeOther{
@MyAnnotation("ABC")
public String someMethod(String name){
}
}
在上面的类中我在@MyAnnotation中传递“ABC”。现在我如何在SomeAspect.java类的procede方法中访问“ABC”值?
谢谢!
你可以从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);
实际上我认为我们可以用另一种方式获得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
。
这也适用 - 您可以使用类上的反射来获取注释信息。
Annotation anno = MyClass.class.getAnnotation(MyAnnotation.class);
要么
Annotation anno = MyClass.class.getDeclaredMethod("somethod").getAnnotation(MyAnnotation.class);
仅当您的注释在运行时可用时才有效,您已正确声明了该注释。
@Retention(RetentionPolicy.RUNTIME)
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)