2011-09-08 53 views
1

我試圖將此ControllerAnnotationHelper轉換爲服務,並且出現了奇怪的問題。無法調用需要java.lang.Class參數的方法?

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) 
} 

我怎樣才能宣佈這個方法,這樣我可以打電話它與一個控制器類和cl各種註釋界面的屁股?

+0

這適用於我。有一件很奇怪的事情是,您保留了受保護的訪問權限,但您將其稱爲公共方法。它有助於刪除「受保護的」(因爲默認範圍是公開的)還是明確公開?另外 - 嘗試運行'grails clean'強制重新編譯。 –

+0

我沒有嘗試'grails clean',但它被'保護',所以我可以從集成/單元測試中打它。我會嘗試明天去除靜態修飾符/清理/公共訪問。值得注意的是我正在運行1.3.7,所以這可能是1.7.x版本的問題。 –

+0

@Burt Beckwith:很奇怪。它看起來像(在運行之間有一個乾淨的),只有當這個方法是公開的時候,這纔有效。如果標記爲protected,那麼init方法和測試都不能調用findAnnotatedClosures方法。我不明白這一點。 –

回答

1

在服務非公有制方法,一般也不會太大的意義。特別是在Grails中,由於缺省情況下服務是事務性的,所以它將會產生問題,因此您將使用的實例將成爲代理。

只有公共方法被代理。受保護的方法是有效的,但通常只在子類和子類/超類中進行子類化和調用時才使用。

所以它歸結爲一個Groovy/Spring的東西。我們習慣了Groovy不嚴格限制訪問規則,但Grails服務幾乎是純粹的Spring bean - Grails只是讓你在Groovy中編寫它們,自動創建關聯的Spring bean,並自動使它們成爲事務性的(除非它被禁用)。

由於您繞過代理並直接轉到真實的類,因此使該方法成爲靜態也行得通,並且Groovy允許您在即使受保護的情況下也可以調用它。

+0

我有交易錯誤,也許它不是直接與grails模型保持一致,但是所有響應'init()'的服務都在引導時獲得初始化,並且作爲服務(bean),我可以輕鬆地在需要的地方注入。我想我覺得奇怪的是其他保護方法正常工作。 –

0

那麼,這是奇怪,我無法解釋,但是,這個調用工作只有在方法聲明爲static靜態和使用。它不能從服務的實例中調用。

保持該方法靜態,它會工作。如果別人可以解釋這一點,我會拋棄接受和贊成。

-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肯德爾是正確的。如果方法test_findAnnotatedClosures()不依賴於任何實例,則最好是— ,儘管不要求 —聲明它爲static並且從靜態上下文中引用它。但那不是重點。

+1

不,你錯了。在Groovy中,您可以通過原始類名訪問類引用。 MyController和MyController.class以完全相同的方式失敗。 –

+0

我的歉意。我沒有意識到OP正在使用Groovy編寫代碼。我一定錯過了他所說的那部分。 (我也不知道Groovy是什麼。)但是,我錯了嗎?或僅僅是無益的?它們是有區別的。 – chharvey

+0

你認爲我在用什麼語言? 'def map = [:]'和'groovy'和'grails'標籤應該已經給出了它。答案是不正確和無益的,直接回答你的問題。我不是故意的。 –

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)

+0

那麼,這可能是一個更合適的定義,但是這會影響我的作品 - 從靜態上下文但不是非實例問題? –

+0

也許不會,因爲可變參數將成爲一個Class [],但我不確定,現在也沒有Groovy訪問。 –

相關問題