Extracting the annotation value using java reflect

2019-09-05 22:16发布

问题:

I have below classes.

I autowired someDao in service class as @Autowired SomeDao someDao. I call the logic in service as someDao.getName(2);

SomeServiceImpl.java

public class SomeServiceImpl{

@Autowired SomeDao someDao
//call dao methods using someDao
}

SomeDao.java

public  interface SomeDao{

 String getName(Int id);
}

SomeDaoImpl.java

public class SomeDaoImpl implements SomeDao{

 @CustomAnnotation("somevalue")
 public String getName(int id){
   //logic

  }


}

SomeAspect.java

@Around("execution(public * *(..)) && @annotation(com.mycompany.CustomAnnotation)")
    public Object procedeNext(ProceedingJoinPoint call) throws Throwable {

  //Access annotation value
        MethodSignature signature = (MethodSignature) call.getSignature();
        Method method = signature.getMethod();
        CustomAnnotation myAnnotation =   method.getAnnotation(CustomAnnotation.class);
        String name = myAnnotation.value();
            //here i am expecting name value "somevalue" but it is returning null


}

CustomAnnotation has @Retention(RetentionPolicy.RUNTIME).

In above aspect, String name = myAnnotation.value(); should give me somevalue but it is giving null. Any suggestion? But if I keep @CustomAnnotation("somevalue") in interface then it gives value. Is it good to annotate interface methods?

回答1:

It's because the default spring APO proxy gets the methods from the interface and not the class. So when the method call is the one from the interface and not the class.

You have several choices:

1.either you change your xml configuration to <aop:config proxy-target-class="true"> and it should work since the proxy will get the class and not the interface. If you have several xml aop config, and if one of them targets the target class then all of them will do the same so be careful.

2.Or you stick with the default and then you put your annotations on the interface. That works perfectly fine as long as you are careful with your annotations. Especially if you have transactions.

3.There might be an other solution using the method call to get the target class using ClassUtils to get the class behind the proxyed interface, but I did not look to much into it.

Hope this helps