web-dev-qa-db-ja.com

ProceedingJoinPointからメソッドの注釈値を取得する方法は?

以下の注釈があります。

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){


}


}

上記のクラスでは、「[〜#〜] abc [〜#〜] "in @ MyAnnotation」を渡します。 「[〜#〜] abc [〜#〜] value in procede method of SomeAspect.Java class?」にアクセスするにはどうすればよいですか?

ありがとう!

47
user755806

ProceedingJoinPoint から Signature を取得でき、メソッド呼び出しの場合は 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();
_

[〜#〜] edit [〜#〜]

クラスレベルで@MyAnnotation( "ABC")がある場合に値を取得する方法は?

ClassAnnotatedElement でもあるため、Methodと同じ方法で取得できます。例えば。メソッドの宣言クラスの注釈は、次を使用して取得できます。

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

スプリングを使用しているため、スプリングの AnnotationUtils.findAnnotation(..) を使用することもできます。 springと同じように注釈を検索します。例えば。また、スーパークラスやインターフェイスメソッドなども調べます。

_ MyAnnotation foundAnnotation = AnnotationUtils.findAnnotation(method, MyAnnotation.class);
_
101
René Link

実際、ProceedingJoinPointからだけでなく、別の方法でvalueを取得できると思います。 reflection

アノテーションを直接使用して、次のように試してください。com.mycompany.MyAnnotation yourAnnotationadvice paramsを追加し、@Around@annotation(yourAnnotation)を追加します。

@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を検索するだけです。

14
Hearen

これも機能します-クラスのリフレクションを使用して、注釈情報を取得できます。

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

または

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

これは、正しく宣言されている注釈が実行時に使用可能な場合にのみ機能します。

@Retention(RetentionPolicy.RUNTIME)
3
Martin Frey

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;
    }
0
Rajeev Rathor

René'sの例は長い道のりを歩んでいます。また、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";
}

「controllerPackage」の値を受け取りたい「SwaggerConfiguration」に関する構成をインポートしています

@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.classSwaggerConfiguration(Swagger Stuff別のライブラリで)私は次のような単純なリフレクションを使用することはできません

Application.class.getAnnotation(EnableSwaggerApi.class)
0
Tom K.