spring @Autowire property vs setter

anotate @Autowired与某个属性有什么区别,或者在setter中执行它有什么区别?

据我所知他们都有相同的结果,但有没有理由使用一个而不是另一个?

更新(更简洁)

这有什么不同吗?

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

使用@Autowired注释,您不需要setter方法。 一旦你的bean的构造函数完成了分配/创建对象,Spring将扫描这个注释并注入你注释的对象实例。

如果您有setter并且如果您仍在使用xml配置,那么您将显式设置属性。

话虽如此,你可以使用autowired注释来注释你的构造函数和setter方法,我更喜欢这样,因为这会让我有灵活性以后离开Spring(虽然我不会这样做)。

有时您需要A类的实例,但是您不在类的字段中存储A. 你只需要A来执行一次性操作。 或者,使用A获取B的实例,并在字段中存储B.

在这些情况下,setter(或构造函数)autowire将更适合您。 您将没有未使用的类级别字段。

具体示例:您需要构造RabbitTemplate (一个向RabbitMQ发送消息的对象)要构造它,您需要ConnectionFactory http://docs.spring.io/spring-amqp/docs/latest_ga/api/org/springframework/amqp/兔/型芯/ RabbitTemplate.html#RabbitTemplate-org.springframework.amqp.rabbit.connection.ConnectionFactory-

您不需要存储ConnectionFactory。 在这种情况下,代码看起来像这样:

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

…比直接自动assemblyConnectionFactory字段更能为您服务。

在此示例中,构造函数级别的自动assembly会更好,因为您的对象将始终完全构造。 很明显, ConnectionFactory是一个强制依赖,而不是一个可选的依赖。

如果可以,你应该避免使用setter。 如果你不需要它,那么当它不存在时会更好,对吗?

我个人更喜欢Guice允许我写作

 public class TextEditor { private final SpellChecker spellChecker; @Inject public TextEditor(SpellChecker spellChecker) { this.spellChecker = spellChecker; } public void spellCheck(){ spellChecker.checkSpelling(); } } 

这更进了一步:对于final字段,我知道它不会改变,我得到multithreading可见性保证 。

如果在@Autowired 使用@Autowired批注,spring将使用spring.xml启动该属性。 在这种情况下,您不需要setter。

如果setter使用@Autowired注释,则指定它应该使用此setter方法启动此属性,您可以在其中添加自定义代码,例如使用此属性初始化某些其他属性

用例与示例:在使用JdbcTemplate使用DAO操作的情况下,需要DataSource作为JdbcTemplate的输入,但DataSource本身不需要作为属性。 因此,您可以使用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); } 

在上面的代码中,dataSource的唯一用途是在JdbcTemplate中传递。 因此,创建dataSource的属性在这里没有意义。 因此,只需使用@Autowired on DataSource bean的setter方法从spring.xml获取它的条目,并在特定时间使用它。

自动assembly在项目中一致使用时效果最佳。 如果一般不使用自动assembly,那么开发人员使用它来连接一个或两个bean定义可能会让人感到困惑。 在一个字段上使用@Autowired,你不需要一个setter方法,它一方面使类更小,更容易阅读,但另一方面使得模拟类更加丑陋。

property和constructor-arg设置中的显式依赖项始终覆盖自动assembly。 您无法自动assembly所谓的简单属性,例如基元,字符串和类(以及此类简单属性的数组)。 这种限制是按设计的。

自动assembly不如显式布线精确。 Spring会小心避免在可能产生意外结果的歧义的情况下进行猜测,因此不再明确记录Spring管理对象之间的关系。

可能无法为可能从Spring容器生成文档的工具提供接线信息。

容器中的多个bean定义可能与要自动assembly的setter方法或构造函数参数指定的类型匹配。 对于数组,集合或地图,这不一定是个问题。 但是,对于期望单个值的依赖关系,这种模糊性不是任意解决的。 如果没有可用的唯一bean定义,则抛出exception。

有一种情况是在OPTIONAL属性上使用@Autowired不起作用。

如果要使用该属性进行初始化,则可能在调用构造函数之前未设置它,并且由于它是可选的,因此不能将其作为构造函数中的参数。

在这种情况下,最好使用@Autowired setter方法,以便在属性自动assembly后执行初始化。