当通过CGLIB进行代理时,方法注释为null

时间:2012-01-23 15:56:05

标签: java spring reflection annotations cglib

当通过反射查看属于通过CGLIB代理的类的方法的注释时,我遇到了一种奇怪的行为。我们在Spring中使用CGLIB,如果我仅使用注释注释方法,它就可以正常工作(我可以通过对应的getAnnotations()对象上的Method方法检索注释)。如果我使用2个注释来注释方法(无论注释顺序如何),getAnnotations()只返回null。两个注释都有RetentionPolicy.RUNTIME

我读过CGLIB存在一些问题,但奇怪的是它只适用于一个注释,当我输入2个注释时它返回null。

有什么建议吗?

(使用Spring 3.0.5和CGLIB 2.2.2)

添加代码:

第一个注释是:

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Produces {
    ResultType[] value();
}

第二个注释是

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface JamonMonitored {
    String type() default "";
    String tag() default "";
}

代码块用于检查注释

Collection<Method> candidates = Collections2.filter(Arrays.asList(executorInstance.getClass().getMethods()), new Predicate<Method>() {
    @Override
    public boolean apply(Method input) {
        return input.getAnnotation(Produces.class) != null;
    }
});

if (candidates.isEmpty()) {
    // throws exception
}

如果我使用@Produces和@JamonMonitored批注方法,getAnnotation(Produces.class)始终为null

2 个答案:

答案 0 :(得分:16)

CGLIB通过生成目标对象的类的子类来工作,并且该子类生成了委托给目标对象的方法。当您使用反射来查询代理对象的注释时,您要求在代理类上进行注释,而不是目标对象的类。

Spring必须自己进行大量的注释处理,以便在代理,超类,接口等方面进行导航。执行此操作的逻辑被封装并在org.springframework.core.annotation.AnnotationUtils类中公开。在你的情况下,听起来你想要findAnnotation utility method,即

@Override
public boolean apply(Method input) {
    return AnnotationUtils.findAnnotation(input, Produces.class) != null;
}

答案 1 :(得分:1)

另一种选择是在注释定义中指定@Inherited。这将使注释出现在cglib生成的子类中。当然,在某些情况下,您不希望您的注释出现在“真实”子类中,因此这可能不是每个场景的选项,而且可以使用如skaffman所示的Spring助手