2011-08-02 36 views
11

在我的項目中,所有客戶端類都有一個公共基類。這有一個@Autowired字段需要由Hibernate注入。這些都是在另一個具有基類的@Autowired集合的類中組合在一起的。無法讓@Component在Spring中繼承?

爲了減少客戶端代碼的樣板我試圖讓@Component被繼承。隨着@Component默認情況下不這樣做(顯然it used to though),我創造了這個解決辦法註釋

@Target(ElementType.TYPE) 
@Retention(RetentionPolicy.RUNTIME) 
@Component 
@Inherited 
public @interface InheritedComponent { 
} 

...與它註釋的基類。它不漂亮,但我希望它能起作用。不幸的是,它並沒有真正讓我感到困惑,因爲@Inherited應該讓它工作

是否有任何其他方式獲得@Component繼承?還是我不得不說,任何擴展基類的類都需要這個樣板文件?

回答

9

問題是Component註釋類型本身需要標記@Inherited

@InheritedComponent註釋類型被正確地擴展標記有@InheritedComponent超類的類繼承的 - 但它沒有繼承@Component。這是因爲您在註釋上有@Component,而不是父類型。

一個例子:

public class InheritedAnnotationTest { 

    @InheritedComponent 
    public static class BaseComponent { 
    } 

    public static class SubClass extends BaseComponent { 
    } 

    public static void main(String[] args) { 
     SubClass s = new SubClass(); 

     for (Annotation a : s.getClass().getAnnotations()) { 
      System.out.printf("%s has annotation %s\n", s.getClass(), a); 
     } 
    } 
} 

輸出:

類brown.annotations.InheritedAnnotationTest $子類有註釋@ brown.annotations.InheritedComponent()

換句話說,當解析一個類有什麼註釋時,註解的註解不會被解析 - 它們不適用於類,只適用於註釋(如果t帽子是有道理的)。

+0

嗯,我認爲我可以這樣做,因爲'@ Repository'這樣的東西用'@ Component'註解。猜猜我只需要發出一個很大的警告,說:「如果你擴展這個類,你必須*用'@ Component'註釋它的樣板。 – TheLQ

+1

我相信那些工作,因爲掃描組件註釋的Spring類有特殊的邏輯來檢查註釋的註釋 - 看看ClassPathScanningCandidateComponentProvider和AnnotationTypeFilter。可能還有一種方法可以使您的組件註釋註釋工作 –

7

我已經通過創建我自己的註解(遺傳),然後定製類路徑掃描處理這個問題:

@Target(ElementType.TYPE) 
@Retention(RetentionPolicy.RUNTIME) 
@Component 
@Inherited 
public @interface BusinessService { 
} 

Spring配置看喜歡這樣的:

<context:component-scan base-package="io.bar"> 
     <context:include-filter type="annotation" 
      expression="io.bar.core.annotations.BusinessService" /> 
    </context:component-scan> 

Spring doc 5.10.3 Using filters to customize scanning