无法调用需要 java.lang.Class 参数的方法?
我正在尝试将此 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)
}
如何声明此方法,以便可以使用控制器类和各种注释接口的类来调用它?
I'm trying to convert this ControllerAnnotationHelper into a service, and I'm getting weird issues.
No signature of method AnnotationScannerService.findAnnotatedClosures() is applicable for argument types:
(java.lang.Class, java.lang.Class) values: [class MyController, interface MyAnnotationRequired]
Here's the original method:
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
}
and mine:
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
}
With invocation:
public void test_findAnnotatedClosures() {
Map<String, List<Class>> annotatedClosures =
annotationScannerService.findAnnotatedClosures(MyController, MyRequiredAnnotation)
}
How can I declare this method such that I can call it with a controller class and the class of various annotation interfaces?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
一般来说,服务中的非公共方法没有多大意义。特别是在 Grails 中,这会出现问题,因为默认情况下服务是事务性的,因此您将使用的实例将是代理。
仅代理公共方法。受保护的方法是有效的,但通常仅在类或子/超类内进行子类化和调用时使用。
所以它归结为 Groovy/Spring 的事情。我们习惯了 Groovy 对访问规则不严格,但 Grails 服务几乎纯粹是 Spring bean - Grails 只是让您在 Groovy 中编写它们,自动创建关联的 Spring bean,并自动使它们成为事务性的(除非禁用)。
使方法静态也有效,因为您绕过代理并直接进入真正的类,并且 Groovy 允许您调用它,即使它是受保护的。
A non-public method in a service doesn't make much sense in general. In particular in Grails it's going to be problematic since by default services are transactional, so the instance you'll be working with will be a proxy.
Only public methods are proxied. Protected methods are valid, but would typically just be used when subclassing and calling within the class or sub/super class.
So it boils down to a Groovy/Spring thing. We're used to Groovy not being strict about access rules, but Grails services are almost purely Spring beans - Grails just lets you write them in Groovy, auto-creates the associated Spring bean, and automatically makes them transactional (unless that's disabled).
Making the method static also works since you're bypassing the proxy and going directly to the real class, and Groovy lets you call it even though it's protected.
嗯,这很奇怪,我无法解释它,但只有当该方法声明为静态并静态使用时,此调用才有效。无法从服务的实例调用它。
保持该方法静态,它就会起作用。如果其他人可以解释这一点,我会放弃接受并投票。
Well, this is odd, and I can't explain it, but this invocation works only if the method is declared static and used statically. It cannot be called from an instance of the service.
Keep the method static, and it'll work. If someone else can explain this, I'll toss over the accept and upvote.
也许这取决于常规版本。在 groovy 1.7 中,所有通用类型信息都被删除,从 1.8 开始则没有。正确的方法声明是:
因为
isAnnotationPresent(ClassannotationClass)
Maybe this depends on the groovy version. With groovy 1.7 all generic type info is removed, from 1.8 not. The right method declaration is:
because of
isAnnotationPresent(Class<? extends Annotation> annotationClass)
每个类都是该类的一个实例
Class< T>
(我知道这很令人困惑),其中类型参数T
是“此Class
对象建模的类的类型”。换句话说,您的类MyController
是Class
类型的对象。每个类都有一个隐藏的静态字段,称为
class
。如果您想访问MyController
类本身,请使用声明MyController.class
。这将返回Class
的实例,并且MyController.class
可用的所有方法和字段都是任何Class
对象可用的方法和字段。例如,getName ()
。总而言之,您的调用代码应为:
PS:@Stefan Kendall 是正确的。如果方法
test_findAnnotatedClosures()
不依赖于任何实例,则最好将其声明为static
并从静态上下文。但这不是重点。Every class is an instance of the class
Class<T>
(confusing, I know), where the type parameterT
is "the type of the class modeled by thisClass
object." In other words, your classMyController
is an object of typeClass<MyController>
.And every class has a hidden static field called
class
. If you want to access theMyController
class itself, use the declarationMyController.class
. This will return an instance ofClass<MyController>
, and all the methods and fields available toMyController.class
are those available to anyClass
object. For example,getName()
.All in all, your invocation code should read:
PS: @Stefan Kendall is correct. If the method
test_findAnnotatedClosures()
is not dependent on any instances, it is best—though not required—to declare itstatic
and reference it from a static context. But that is beside the point.