복붙노트

[SPRING] Spring AOP : 인수 이름에 접근하기

SPRING

Spring AOP : 인수 이름에 접근하기

저는 Spring 3.x, Java 6을 사용하고 있습니다.

나는 다음 joinpoint를 가진 @Around aspect를 가진다.

@Around("execution(public * my.service.*.*Connector.*(..))")

그래서 저는 기본적으로 클래스 이름이 "Connector"로 끝나는 클래스의 공용 메소드에 대한 모든 호출을 인터셉트하는 것에 관심이 있습니다. 여태까지는 그런대로 잘됐다.

자, 내 측면에서 메서드의 실제 인수 이름에 액세스하고 싶습니다 :

public doStuff(String myarg, Long anotherArg)

myarg 및 anotherArg

나는 그것을 사용하는 것을 이해한다 :

CodeSignature signature = (CodeSignature)jointPoint.getSignature();
return signature.getParameterNames();

실제로 작동하지만, "-g"플래그 (전체 디버그)로 코드를 컴파일하고 오히려 수행하지 않을 경우에만 가능합니다.

이러한 종류의 런타임 정보에 액세스 할 수있는 다른 방법이 있습니까?

감사 엘

해결법

  1. ==============================

    1.유감스럽게도 JVM / 바이트 코드의 잘 알려진 제한 사항입니다. 리플렉션을 사용하여 인수 이름을 얻을 수 없습니다. 메소드 이름 / 클래스 이름과는 달리 바이트 코드에 항상 저장되는 것은 아니기 때문에 리플렉션을 사용하여 인수 이름을 얻을 수 없습니다. .

    유감스럽게도 JVM / 바이트 코드의 잘 알려진 제한 사항입니다. 리플렉션을 사용하여 인수 이름을 얻을 수 없습니다. 메소드 이름 / 클래스 이름과는 달리 바이트 코드에 항상 저장되는 것은 아니기 때문에 리플렉션을 사용하여 인수 이름을 얻을 수 없습니다. .

    해결 방법으로 여러 프레임 워크 / 사양에서는 WebParam (이름 속성) 또는 PathParam과 같은 인수를 통해 사용자 지정 주석을 사용합니다.

    주석없이 얻을 수있는 모든 시간은 가치의 배열입니다.

  2. ==============================

    2.org.springframework.core.ParameterNameDiscoverer의 구현을 확인하십시오.

    org.springframework.core.ParameterNameDiscoverer의 구현을 확인하십시오.

    spring이 사용하는 @RequestParam과 같은 주석은 값이 설정되지 않은 경우 매개 변수 이름을 검사합니다. 따라서 @RequestParam String foo는 사실 "foo"라는 요청 매개 변수를 가져옵니다. ParameterNameDiscoverer 메커니즘을 사용합니다. 각 구현을 사용하여 어떤 구현을 사용하는지 확실하지 않습니다.

    LocalVariableTableParameterNameDiscoverer는 .class를 읽고 asm을 사용하여 이름을 검사합니다.

    그래서 가능합니다. 그러나이 정보를 캐시해야합니다 (예 : 키 = 클래스 + 메소드 + 매개 변수 색인과 함께 매개 변수 이름을 맵에 저장).

    그러나 문서에서 언급했듯이 디버그 정보가 필요합니다. @PathVariable의 문서에서 :

    그래서, 정말로 그 정보를 포함하고 싶지 않다면, Tomasz Nurkiewicz의 답은 그 해결 방법을 설명합니다.

  3. ==============================

    3.Java 8에는 추가 메타 데이터를 바이트 코드와 함께 저장할 수있는 새로운 컴파일러 플래그가 있으며 이러한 매개 변수 이름은 리플렉션의 Parameter 객체를 사용하여 추출 할 수 있습니다. JDK 8 스펙을 참조하십시오. 최신 버전의 hibernate에서는 org.springframework.core.ParameterNameDiscoverer가이 기능을 사용한다. 이 플래그로 javac를 사용하여 컴파일하려면 다음을 수행하십시오.

    Java 8에는 추가 메타 데이터를 바이트 코드와 함께 저장할 수있는 새로운 컴파일러 플래그가 있으며 이러한 매개 변수 이름은 리플렉션의 Parameter 객체를 사용하여 추출 할 수 있습니다. JDK 8 스펙을 참조하십시오. 최신 버전의 hibernate에서는 org.springframework.core.ParameterNameDiscoverer가이 기능을 사용한다. 이 플래그로 javac를 사용하여 컴파일하려면 다음을 수행하십시오.

    -parameters                Generate metadata for reflection on method parameters
    

    리플렉션의 Parameter 클래스를 사용하여 매개 변수에 액세스합니다.

  4. ==============================

    4.가장 좋은 방법인지 확실하지 않지만 내 방법에 대한 주석을 추가했습니다.

    가장 좋은 방법인지 확실하지 않지만 내 방법에 대한 주석을 추가했습니다.

    내 주석 :

    @Retention (RetentionPolicy.RUNTIME)
    @Target (ElementType.METHOD)
    public @interface ReadApi
    {
        String[] paramNames() default "";
    }
    
    @ReadApi (paramNames={"name","id","phone"})
    public Address findCustomerInfo(String name, String id, String phone)
    { ..... }
    

    그리고 측면 :

    @Around("aspect param && @annotation(readApi)")
    public Object logParams(ProceedingJoinPoint pjp,
            ReadApi readApi) 
    {
        //use pjp.getArgs() and readApi.paramNames();
    }
    

    이것은 아마 해킹이지만 정보를 얻기 위해 더 많은 옵션으로 컴파일하고 싶지 않았습니다. 어쨌든, 나를 위해 잘 작동합니다. 유일한 단점은 내가 주석과 메소드에서 이름을 동기화하여 유지해야한다는 것입니다.

  5. from https://stackoverflow.com/questions/5030638/spring-aop-get-access-to-argument-names by cc-by-sa and MIT license