无法调用需要java.lang.Class参数的方法?

时间:2011-09-08 18:10:41

标签: java grails groovy annotations closures

我正在尝试将此ControllerAnnotationHelper转换为服务,而且我遇到了奇怪的问题。

No signature of method AnnotationScannerService.findAnnotatedClosures() is applicable for argument types:
(java.lang.Class, java.lang.Class) values: [class MyController, interface MyAnnotationRequired]

这是原始方法:

private static Map<String, List<Class>> findAnnotatedClosures(
      Class clazz, Class... annotationClasses) {
   def map = [:]
   for (field in clazz.declaredFields) {
      def fieldAnnotations = []
      for (annotationClass in annotationClasses) {
         if (field.isAnnotationPresent(annotationClass)) {
            fieldAnnotations << annotationClass
         }
      }
      if (fieldAnnotations) {
         map[field.name] = fieldAnnotations
      }
   }

   return map
}

和我的:

protected Map<String, List<Class>> findAnnotatedClosures(Class clazz, Class... annotationClasses) {
   def map = [:]
   for (field in clazz.declaredFields) {
      def fieldAnnotations = []
      for (annotationClass in annotationClasses) {
         if (field.isAnnotationPresent(annotationClass)) {
            fieldAnnotations << annotationClass
         }
      }
      if (fieldAnnotations) {
         map[field.name] = fieldAnnotations
      }
   }

   return map
}

通过调用:

public void test_findAnnotatedClosures() {
   Map<String, List<Class>> annotatedClosures =
        annotationScannerService.findAnnotatedClosures(MyController, MyRequiredAnnotation)
}

如何声明此方法,以便我可以使用控制器类和各种注释接口的类来调用它?

4 个答案:

答案 0 :(得分:1)

服务中的非公共方法通常没有多大意义。特别是在Grails中,它会有问题,因为默认服务是事务性的,因此您将使用的实例将是代理。

仅代理公共方法。受保护的方法是有效的,但通常只在子类和子类/超类中进行子类化和调用时使用。

所以归结为一个Groovy / Spring的东西。我们已经习惯了Groovy对访问规则的严格要求,但Grails服务几乎完全是Spring bean - Grails只允许你用Groovy编写它们,自动创建相关的Spring bean,并自动使它们成为事务性的(除非它被禁用)。

使方法保持静态也有效,因为你绕过代理并直接进入真正的类,而Groovy允许你调用它,即使它受到保护。

答案 1 :(得分:0)

嗯,这很奇怪,我无法解释它,但只有当方法声明为静态并静态使用时,此调用才能。无法从服务实例调用它。

保持方法静态,它会起作用。如果其他人可以解释这一点,我会抛弃接受和upvote。

答案 2 :(得分:0)

也许这取决于groovy版本。使用groovy 1.7删除所有通用类型信息,而不是1.8。正确的方法声明是:

protected Map<String, List<Class<? extends Annotation>>> findAnnotatedClosures(Class<?> clazz, Class<? extends Annotation>... annotationClasses)

因为isAnnotationPresent(Class<? extends Annotation> annotationClass)

答案 3 :(得分:-1)

每个类都是类Class<T>的一个实例(我知道这很混乱),其中类型参数T是“由此Class对象建模的类的类型”。换句话说,您的班级MyControllerClass<MyController>类型的对象

每个类都有一个名为class的隐藏静态字段。如果要访问MyController类本身,请使用声明MyController.class。这将返回Class<MyController>的实例,MyController.class可用的所有方法和字段都可用于任何Class对象。例如,getName()

总而言之,您的调用代码应为:

public void test_findAnnotatedClosures() {
    Map<String, List<Class>> annotatedClosures =
        annotationScannerService.findAnnotatedClosures(MyController.class,
            MyRequiredAnnotation.class)
}
PS:@Stefan Kendall是对的。如果方法test_findAnnotatedClosures()不依赖于任何实例,则最好 - 虽然不需要 - 声明它static并从静态上下文引用它。但这不是重点。