Не удается вызвать метод, требующий аргументов java.lang.Class? - PullRequest
1 голос
/ 08 сентября 2011

Я пытаюсь преобразовать 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 ]

1 голос
/ 09 сентября 2011

Непубличный метод в сервисе не имеет большого смысла в целом. В частности, в Grails это будет проблематично, поскольку по умолчанию сервисы являются транзакционными, поэтому экземпляр, с которым вы будете работать, будет прокси.

Только публичные методы проксируются. Защищенные методы допустимы, но обычно они используются только при создании подклассов и вызовах внутри класса или подкласса / суперкласса.

Так что все сводится к Groovy / Spring. Мы привыкли к тому, что Groovy не является строгим в отношении правил доступа, но службы Grails - это почти чисто bean-компоненты Spring - Grails просто позволяет писать их в Groovy, автоматически создает связанный Spring-бин и автоматически делает их транзакционными (если это не отключено).

Создание статического метода также работает, поскольку вы обходите прокси-сервер и переходите непосредственно к реальному классу, а Groovy позволяет вам вызывать его, даже если он защищен.

0 голосов
/ 08 сентября 2011

Каждый класс является экземпляром класса Class<T> (я знаю, что он сбит с толку), где параметр типа T - это "тип класса, моделируемого этим объектом Class".Другими словами, ваш класс MyController является объектом типа Class<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 и ссылаться на него из статического контекста.Но это не относится к делу.

0 голосов
/ 08 сентября 2011

Возможно, это зависит от отличной версии. С groovy 1.7 вся информация о типовых типах удаляется, с 1.8 нет. Правильное объявление метода:

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

из-за isAnnotationPresent(Class<? extends Annotation> annotationClass)

0 голосов
/ 08 сентября 2011

Ну, это странно, и я не могу это объяснить, но этот вызов работает , только если метод объявлен как статический и используется статически. Его нельзя вызвать из экземпляра службы.

Сохраняйте метод статичным, и он будет работать. Если кто-то еще может объяснить это, я переброшу согласие и одобрение.

...