2015-11-06 67 views
18

anotate @Autowired與屬性之間的區別或在setter中執行的區別是什麼?spring @Autowire property vs setter

據我所知,他們都具有相同的結果,但沒有任何理由使用一個比其他?

UPDATE(更簡潔)

是否有這個

package com.tutorialspoint; 

import org.springframework.beans.factory.annotation.Autowired; 

public class TextEditor { 
    private SpellChecker spellChecker; 

    @Autowired 
    public void setSpellChecker(SpellChecker spellChecker){ 
     this.spellChecker = spellChecker; 
    } 

    public void spellCheck() { 
     spellChecker.checkSpelling(); 
    } 
} 

package com.tutorialspoint; 

import org.springframework.beans.factory.annotation.Autowired; 

public class TextEditor { 
    @Autowired 
    private SpellChecker spellChecker; 

    public TextEditor() { 
     System.out.println("Inside TextEditor constructor."); 
    } 

    public void spellCheck(){ 
     spellChecker.checkSpelling(); 
    } 
} 
+0

我不知道爲什麼這個問題的答案會被置之度外。我想知道在setter中或直接在屬性中使用@Autowired是否有實際區別。不要問哪一個更好,只是如果有差異 – luso

回答

14

隨着@Autowired註釋之間的區別,你並不需要一個二傳手方法。一旦你的bean的構造函數完成了分配/創建對象的工作,Spring將掃描這個註解並注入你註釋的對象實例。

而如果你有二傳手,如果你還在使用XML配置,你會明確設置的屬性。說了這麼多,你可以使用autowired註釋來註釋你的構造函數和setter方法,我更喜歡這樣做,這會給我以後的彈性(儘管我不會這樣做)。

+0

正如在我用來更新帖子的Spring示例中,DI術語中是否有任何區別? – luso

+0

沒有區別,你仍然注入依賴。這只是您的構造函數或設置者的選擇,例如 – SMA

0

自動裝配在項目中一致使用時效果最佳。如果一般不使用自動裝配,開發人員可能會使用它來僅連接一個或兩個bean定義。使用@Autowired在一個領域,你不需要一個setter方法,它一方面使得這個類變得更小,更容易閱讀,另一方面讓這個類嘲笑這個類更加醜陋。

屬性和構造函數arg設置中的顯式依賴關係總是覆蓋自動裝配。您不能自動調用所謂的簡單屬性,如基元,字符串和類(以及這些簡單屬性的數組)。這個限制是通過設計。

自動裝配不如準確佈線。 Spring很小心避免在可能有意想不到的結果的情況下進行猜測,因此Spring管理的對象之間的關係不再被明確記錄。

接線信息可能無法用於可能從Spring容器生成文檔的工具。在容器內

多個bean定義可以匹配由設定器方法或構造參數中指定的類型來自動裝配。對於數組,集合或地圖,這不一定是個問題。然而,對於期望單一值的依賴關係,這種不明確性不是任意解決的。如果沒有唯一的bean定義可用,則拋出異常。

1

如果可以,你應該避免使用setter。如果你不需要它,它不存在的時候會更好,對嗎?

我個人比較喜歡吉斯讓我寫

public class TextEditor { 
    private final SpellChecker spellChecker; 

    @Inject public TextEditor(SpellChecker spellChecker) { 
     this.spellChecker = spellChecker; 
    } 

    public void spellCheck(){ 
     spellChecker.checkSpelling(); 
    } 
} 

這更進了一步:用final場,我知道這永遠不會改變,我得到的multithreading visibility guarantee

6

有時你需要一個類A的實例,但是你不在類的字段中存儲A.您只需要A執行一次性操作。或者,您使用A獲取B的一個實例,並且您將B存儲在該字段中。

在這些情況下,setter(或構造函數)autowire將更適合您。您不會有未使用的課程級別字段。

具體的例子: 需要構建RabbitTemplate(發送消息RabbitMQ的一個對象) 構建它,你需要連接工廠 http://docs.spring.io/spring-amqp/docs/latest_ga/api/org/springframework/amqp/rabbit/core/RabbitTemplate.html#RabbitTemplate-org.springframework.amqp.rabbit.connection.ConnectionFactory-

你並不需要存儲連接工廠。在這種情況下,代碼看起來像這樣:

Class MyClass { 
private RabbitTemplate template; 

@Autowired 
void setConnectionFactory(ConnectionFactory c) { 
    template=new RabbitTemplate(c); 
} 
} 

...將竭誠爲您服務不是直接自動裝配的的ConnectionFactory場更好。

在這個例子中,在構造函數級別的自動裝配會更好,因爲你的對象將始終被完全構造。很明顯,ConnectionFactory是強制性的依賴關係,而不是可選的依賴關係。

0

如果您在財產使用@Autowired註釋,Spring將採用spring.xml啓動性能。在這種情況下你不需要setter。

如果您在二傳手使用@Autowired註釋,您指定到春天,它應該使用此setter方法啓動此屬性,您可以添加自定義代碼,如初始化一些其他財產與這個屬性

使用方法與實例: 在使用使用JdbcTemplate的DAO操作的情況下,你需要的DataSource作爲輸入的JdbcTemplate,但數據源不要求本身作爲一種財產。因此,您可以使用DataSource Setter通過自動連接DataSource Setter來初始化JdbcTempate。請看下面的代碼:

class DaoDemo{ 
    //@Autowired 
    //private DataSource dataSource; 
    private JdbcTemplate jdbcTemplate; 

    @Autowired 
    public void setDataSource(DataSource dataSource){ 
    //this.dataSource = dataSource; 
    this.jdbcTemplate = new JdbcTemplate(dataSource); 
    } 

    public int getTableRowCount(){ 
     String sql = "SELECT COUNT(*) FROM DEMOTABLE"; 
     //jdbcTemplate.setDataSource(dataSource); //No need to do this as its done in DataSource Setter now. 
     return jdbcTemplate.queryForObject(sql,Integer.class); 

} 

在上面的代碼,數據源的唯一用途是對的JdbcTemplate獲得通過。因此,創建dataSource的屬性在這裏沒有意義。因此,只需在DataSource bean的setter方法上使用@Autowired來從spring.xml中獲取它的條目,並在該特定時間使用它。

0

有一種情況,在OPTIONAL屬性上使用@Autowired不起作用。

如果您想使用該屬性進行一些初始化,它可能不會在構造函數被調用之前設置,並且由於它是可選的,所以不能將其作爲構造函數中的參數。

在這種情況下,最好使用@Autowired setter方法,以便在屬性自動裝配後執行初始化。