我有以下注释。
@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 ”值?
谢谢!
答案 0 :(得分:93)
您可以从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);
}
但是你应该首先添加一个注释属性。您的示例代码没有,例如</ p>
@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)
。例如。可以使用
MyAnnotation foundAnnotation = AnnotationUtils.findAnnotation(method, MyAnnotation.class);
正如你使用的是春天,你可能也想使用春天的AnnotationUtils.findAnnotation(..)
。它会像spring一样搜索注释。例如。还要查看超类和接口方法等。
{{1}}
答案 1 :(得分:8)
实际上我认为我们可以以另一种方式获得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
即可。
答案 2 :(得分:3)
这也有效 - 您可以使用类上的反射来获取注释信息。
Annotation anno = MyClass.class.getAnnotation(MyAnnotation.class);
或者
Annotation anno = MyClass.class.getDeclaredMethod("somethod").getAnnotation(MyAnnotation.class);
仅当您的注释在运行时可用时才有效,您已正确声明。
@Retention(RetentionPolicy.RUNTIME)
答案 3 :(得分:0)
René的例子使我走了很长一段路。也是我如何获得ClassLevel注释的说明。
但是如果我以前使用带有“ * @ Around(” execution(public * (..))&& @annotation(com.mycompany.MyAnnotation)“的方法注释,那么我只能读取ClassLevel注释值。 )“ ”
我该如何解决?如果设置了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()上的注释?由于 SwaggerConfiguration 不知道 Application.class (Swagger Stuff位于单独的库中),我不能使用
这样的简单反射Application.class.getAnnotation(EnableSwaggerApi.class)
答案 4 :(得分: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;
}
答案 5 :(得分:0)
您可以简单地按照 docs 中的描述绑定方法。
MyAnnotation.java
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation {
}
SomeAspect.java
public class SomeAspect{
@Around("execution(public * *(..)) && @annotation(myAnnotation)")
public Object procede(ProceedingJoinPoint call, MyAnnotation myAnnotation) throws Throwable {
//Some logic
}
}