我正在尝试将此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)
}
如何声明此方法,以便我可以使用控制器类和各种注释接口的类来调用它?
答案 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
对象建模的类的类型”。换句话说,您的班级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
并从静态上下文引用它。但这不是重点。