Spring隐藏的自定义Java Annotation

时间:2015-12-02 17:40:03

标签: java spring reflection annotations

在使用Spring和Jersey的REST服务的上下文中,我创建了一个自定义注释,以便在运行时在方法级别上使用。然后我用它注释了一个方法并通过反射,尝试获得该方法的所有注释,但我总是得到零注释。

自定义注释是这样的:

@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface RestMethod {
}

然后,注释的方法:

@Service
public class SampleExpert extends GenericExpert {
...

    @RestMethod
    public PaginationDTO<SampleDTO> list(SamplePaginationFiltersDTO filters) {
    ...
    }
}

最重要的部分,代码部分尝试获取方法list()的所有注释,它获取零元素数组:

@POST
@Path("/{expert}/{method}")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
public Response post(@PathParam("expert") String expertName, @PathParam("method") String methodName, @Context HttpServletRequest request, String data) {
    try {
        logger.debug("Invoking {}.{}()", WordUtils.capitalize(expertName) + "Expert", methodName);

        // Get Bean and Method.
        WebApplicationContext ctx = WebApplicationContextUtils.getRequiredWebApplicationContext(request.getServletContext());
        GenericExpert expert = (GenericExpert) ctx.getBean(expertName + "Expert");
        Method method = null;
        for (Method m : expert.getClass().getDeclaredMethods()) {
            if (m.getName().equals(methodName)) {
                logger.info("Number of annotations: " + m.getAnnotations().length);
                method = m;
                break;
            }
        }
    ...
}

此处,logger.info(&#34;注释数量:&#34; + ...)始终打印:

18:31:31,837 INFO  [http-apr-8080-exec-7][RestResponder:60] Number of annotations: 0

但是,如果我执行以下操作:

Method m = SampleExpert.class.getMethod("list", SamplePaginationFiltersDTO.class);
logger.info("Number of annotations: " + m.getAnnotations().length);

我得到适当数量的注释(在这种情况下为1)。

我猜Spring是用代理包装方法的,这就是为什么我没有得到方法的注释而是代理中的注释。我还没有找到解决这种情况的方法。

2 个答案:

答案 0 :(得分:3)

我终于得到了我的问题的答案。我需要使用org.springframework.core.annotation.AnnotationUtils实用程序类来检查是否存在注释,如下所示:

AnnotationUtils.findAnnotation(m, RestMethod.class) != null

Spring的AnnotationUtils.findAnnotation()方法正确地克服了CGLIB引入的问题。

答案 1 :(得分:-1)

问题是Spring为你的对象创建了代理,所以当你做

(GenericExpert) ctx.getBean(expertName + "Expert");

您实际上正在获取代理对象,而不是您期望的SampleExpert

@Inherited注释添加到RestMethod注释中。默认情况下,即使是常规子类,也不会继承注释,更不用说代理了。

@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
public @interface RestMethod {
}

如果这不起作用,请确保使用CGLIB代理(它们可能是因为您将它与非接口类一起使用)。