通过 CGLIB 代理时方法注释为 null
当通过反射查找属于通过 CGLIB 代理的类的方法的注释时,我遇到了奇怪的行为。我们在 Spring 中使用 CGLIB,如果我仅使用注释来注释一个方法,它效果很好(我可以通过相应的 Method
getAnnotations() 方法检索注释代码>对象)。如果我用 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
。
I'm experiencing a strange behaviour when looking via reflection for annotations on a method belonging to a class proxied via CGLIB. We use CGLIB in Spring, and if I annotate a method only with an annotation it works well (I'm able to retrieve the annotations via the getAnnotations()
method on the correspondent Method
object). If I annotate the method with 2 annotations instead (no matter the order of annotation), getAnnotations()
just return null
. Both annotation have RetentionPolicy.RUNTIME
.
I read there are some issues with CGLIB, but it's strange that it simply works for one annotation and it returns null when I put 2 annotations.
Any suggestions?
(Using Spring 3.0.5 and CGLIB 2.2.2)
Adding code:
1st annotation is:
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Produces {
ResultType[] value();
}
2nd annotation is
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface JamonMonitored {
String type() default "";
String tag() default "";
}
And the block of code is for checking annotations is
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
}
If I annotate a method with both @Produces and @JamonMonitored, getAnnotation(Produces.class)
is always null
.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
CGLIB 的工作原理是生成目标对象类的子类,并且该子类已生成委托给目标对象的方法。当您使用反射来查询代理对象的注释时,您要求的是代理类的注释,而不是目标对象的类。
Spring 本身必须进行大量注释处理,以便在代理、超类、接口等方面进行导航。执行此操作的逻辑被封装并公开在 org.springframework.core.annotation.AnnotationUtils 类中。就您而言,听起来您想要
findAnnotation
实用方法,即CGLIB works by generating a subclass of the target object's class, and that subclass has generated methods that delegate to the target object. When you use reflection to query the proxy object's annotations, you're asking for annotations on the proxy class, not the target object's class.
Spring has to do a lot of annotation processing itself in order to navigate its way around proxies, superclasses, interfaces and so. The logic for doing this is encapsulated and exposed in the
org.springframework.core.annotation.AnnotationUtils
class. In your case, it sounds like you want thefindAnnotation
utility method, i.e.另一种选择是在注释定义中指定@Inherited。这将使注释甚至出现在 cglib 生成的子类中。当然,在某些情况下,您不希望注释出现在“真正的”子类中,因此这可能不是每个场景的选项,解决方法是使用 Spring 助手,如 skaffman 所示
Another option would be to specify @Inherited within the annotations definition. This would make the annotation appear even in the sub class generated by cglib. Of course in some scenarios you would not want your annotation to appear in "real" subclasses so this might not be an option for every scenario and the way to go is to use the Spring helpers as shown by skaffman