2013-10-21 26 views
16

Spring的@Autowire可以被配置成,如果沒有匹配的自動裝配候選人被發現Spring將不會引發錯誤:@Autowire(required=false)可以@Inject在JSR 330進行選購(如@Autowire(所需= FALSE)

有如果沒有匹配的候選人,等價的JSR-330註釋?@Inject總是失敗。有沒有什麼辦法可以使用@Inject,但是如果沒有找到匹配的類型,框架就不會失敗?我還沒有找到任何相關的文檔範圍

+0

真的不是一個好主意:他們選擇*不*在CDI中做,以確保所有依賴關係都在那裏。如果你真的有一個依賴關係的空檢查?看起來像一個架構問題,一些解決方案可能是注入一個接口,它可能沒有操作的實現。如果沒有找到則爲空是非常糟糕的設計:是故意找不到的,還是因爲編程錯誤? – ymajoros

回答

10

不...在JSR 330中沒有可選的等效...如果你想使用可選的注入,那麼你將不得不堅持使用框架s pecific @Autowired註釋

+1

[我似乎無法找到JSR330的規格文件,如果有的話。](http://www.jcp.org/en/jsr/detail?id=330)你知道背後的原因嗎?決定不包括一種'@可選'功能? –

+1

>>您是否知道不包含某種@可選功能的原因?<<我相信原因在於提供者的存在。 javax.inject.Provider.get()可以返回null,所以如果注入提供者,可以獲得與可選注入 – Male

5

AutowiredAnnotationBeanFactoryPostProcessor(春季3.2)包含此方法,以確定是否需要或不支持的「自動裝配」註釋:

/** 
    * Determine if the annotated field or method requires its dependency. 
    * <p>A 'required' dependency means that autowiring should fail when no beans 
    * are found. Otherwise, the autowiring process will simply bypass the field 
    * or method when no beans are found. 
    * @param annotation the Autowired annotation 
    * @return whether the annotation indicates that a dependency is required 
    */ 
    protected boolean determineRequiredStatus(Annotation annotation) { 
     try { 
      Method method = ReflectionUtils.findMethod(annotation.annotationType(), this.requiredParameterName); 
      if (method == null) { 
       // annotations like @Inject and @Value don't have a method (attribute) named "required" 
       // -> default to required status 
       return true; 
      } 
      return (this.requiredParameterValue == (Boolean) ReflectionUtils.invokeMethod(method, annotation)); 
     } 
     catch (Exception ex) { 
      // an exception was thrown during reflective invocation of the required attribute 
      // -> default to required status 
      return true; 
     } 
    } 

總之,沒有,不是默認。

正由默認尋找方法名稱爲「需要」,這是不上@Inject註釋的字段,從而,methodnulltrue將被返回。

您或許可以通過將此BeanPostProcessor繼承並覆蓋determineRequiredStatus(Annotation)方法來更改該方法,以返回true或更確切地說,「更智能」。

+2

相同的結果或實現您自己的@可選行爲。 –

+0

@SotiriosDelimanolis我假設實現我自己的'@ Optional'行爲將包括建立我自己的BeanPostProccessor的建議,但是這看起來像很多矯枉過正。我發現JSR330沒有包含@Optional註釋是令人遺憾的。 –

+0

@EricB。是的,那將是這樣做的方式。 –

5

這是可以創建一個可選的注入點!

您需要使用注射查找作爲記錄在http://docs.jboss.org/weld/reference/latest/en-US/html/injection.html#lookup

@Inject 
Instance<Type> instance; 

// In the code 
try { 
    instance.get(); 
}catch (Exception e){ 

} 

或類型

@Inject 
Instance<List<Type>> instances 

另外,get()方法,即使所有實例是懶惰的評價,如果你需要。如果沒有發現可以注入的bean,則默認注入將在啓動時評估並拋出異常,當然這個bean會在運行時注入,但如果不可能,應用程序將不會啓動。 在文檔中您將找到更多示例,包括如何過濾注入的實例以及更多。

+0

這隻適用於Weld? – Vadimo

+0

對於任何CDI實施,這不是真的。 –

+0

Ahh好吧,我想我們正在談論JSR-330,這將是JSR-330的解決方案。 – Vadimo

5

實例注入經常被忽略。它增加了很大的靈活性在獲取之前檢查依賴項的可用性。一個不滿意的get會拋出一個很貴的異常。用途:

@Inject 
Instance<SomeType> instance; 
SomeType instantiation; 

if (!instance.isUnsatisfied()) { 
    instantiation = instance.get(); 
} 

您可以限制注射考生正常:

@Inject 
@SomeAnnotation 
Instance<SomeType> instance; 
+0

看到這個答案Giovanni Silva – Tunaki

+0

謝謝!我不知道'javax.enterprise.inject.Instance'類。但是JSR/pkg是它的一部分嗎?它似乎不是JSR-330的一部分。這是JEE6特定的事情嗎? –

+1

java.enterprise.inject.Instance在JSR 299:JavaTM EE平臺的上下文和依賴注入中指定。正如標題所述,它只適用於JEE平臺。 JSR 330:Java依賴注入是一個輕量級的規範,不依賴於JEE平臺。令人遺憾的是,JSR 330沒有包含JSR 299的所有非JEE特有功能,例如java.enterprise.inject.Instance。爲什麼沒有發生,我會留給別人猜測。 –

22

您可以使用java.util.Optional。 如果你正在使用的Java 和你春天版本4.1以上(見here),而不是

@Autowired(required = false) 
private SomeBean someBean; 

你可以只使用與出來的Java 8java.util.Optional類。使用它像:

@Inject 
private Optional<SomeBean> someBean; 

這個實例永遠不會null,你可以使用它像:

if (someBean.isPresent()) { 
    // do your thing 
} 

這樣,你也可以做構造函數注入,與所需的一些豆類和一些豆類可選,具有很大的靈活性

注:不幸的是Spring不支持番石榴com.google.common.base.Optional(見here),因此,如果您使用的是Java 8(或以上),這種方法纔有效。

+2

有趣的選擇。當我最初發布這個問題時,我不在Java8上,但我喜歡這個原則。感謝您指出。我想在技術上,使用JSR330仍然沒有真正的選擇,但這是J8優勢的一個很好的使用來解決它。 –

+0

我正在使用Java 8和Spring 4.2.7,它的功能就像一個魅力。但規範說明如何管理「可選」類型?順便說一下,這是一個非常合理的實現。我喜歡。 – mcoolive

+0

當然,輝煌。正是我所需要的,比一個可選的空bean更清潔。 –

相關問題