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();
}
}
答案 0 :(得分:19)
使用@Autowired
注释,您不需要setter方法。一旦你的bean的构造函数完成了分配/创建对象,Spring将扫描这个注释并注入你注释的对象实例。
如果您有setter,如果您仍在使用xml配置,则应明确设置属性。
话虽如此,你可以使用autowired annotation来注释你的构造函数和setter方法,我更喜欢这样,因为这会让我灵活地离开Spring(虽然我不会这样做)。
答案 1 :(得分:15)
有时你需要一个A类实例,但是你不会在类的字段中存储A.你只需要A来执行一次性操作。或者,使用A获取B的实例,并在字段中存储B.
在这些情况下,setter(或构造函数)autowire将更适合您。您将没有未使用的类级别字段。
具体例子: 您需要构造 RabbitTemplate (一个向RabbitMQ发送消息的对象) 要构建它,您需要 ConnectionFactory http://docs.spring.io/spring-amqp/docs/latest_ga/api/org/springframework/amqp/rabbit/core/RabbitTemplate.html#RabbitTemplate-org.springframework.amqp.rabbit.connection.ConnectionFactory-
您不需要存储ConnectionFactory。在这种情况下,代码如下所示:
Class MyClass {
private RabbitTemplate template;
@Autowired
void setConnectionFactory(ConnectionFactory c) {
template=new RabbitTemplate(c);
}
}
...比直接自动装配 ConnectionFactory 字段更能为您提供服务。
在此示例中,构造函数级别的自动装配会更好,因为您的对象将始终完全构造。很明显, ConnectionFactory 是强制性依赖,而不是可选依赖。
答案 2 :(得分:1)
在整个项目中始终如一地使用自动装配效果最佳。如果一般不使用自动装配,那么开发人员使用它来连接一个或两个bean定义可能会让人感到困惑。在场上使用@Autowired你不需要一个setter方法,这样一方面可以使类更小,更容易阅读,但另一方面使得对类的嘲弄更加丑陋。
property和constructor-arg设置中的显式依赖项始终覆盖自动装配。您无法自动装配所谓的简单属性,例如基元,字符串和类(以及此类简单属性的数组)。这种限制是按设计的。
自动装配不如显式布线精确。 Spring会小心避免在可能产生意外结果的歧义的情况下进行猜测,因此不再明确记录Spring管理对象之间的关系。
可能无法为可能从Spring容器生成文档的工具提供连线信息。
容器中的多个bean定义可能与要自动装配的setter方法或构造函数参数指定的类型匹配。对于数组,集合或地图,这不一定是个问题。但是,对于期望单个值的依赖关系,这种模糊性不是任意解决的。如果没有可用的唯一bean定义,则抛出异常。
答案 3 :(得分:1)
如果可以的话,你应该避开二传手。如果你不需要它,当它不存在时它会更好,对吧?
我个人更喜欢Guice允许我写
@users = User.all.profiles.address.near(params[:search])
@users.joins(:style).where('styles.id = ?', params[:style])
更进了一步:使用public class TextEditor {
private final SpellChecker spellChecker;
@Inject public TextEditor(SpellChecker spellChecker) {
this.spellChecker = spellChecker;
}
public void spellCheck(){
spellChecker.checkSpelling();
}
}
字段,我知道它永远不会改变,我得到了multithreading visibility guarantee。
答案 4 :(得分:1)
如果在属性 上使用PHPFunction(3,-2) result 5
注释,spring将使用spring.xml启动该属性。在这种情况下你不需要setter。
如果您在 setter 上使用@Autowired
注释,则指定应使用此setter方法启动此属性,您可以在其中添加自定义代码,例如使用此属性初始化其他一些属性。
使用示例: 在使用JdbcTemplate使用DAO操作的情况下,您需要DataSource作为JdbcTemplate的输入,但DataSource本身不需要作为属性。因此,您可以使用DataSource Setter通过自动连接DataSource Setter来初始化JdbcTempate。请参阅以下代码:
@Autowired
在上面的代码中,dataSource的唯一用途是在JdbcTemplate中传递。因此,创建dataSource的属性在这里没有意义。因此,只需使用@Autowired on DataSource bean的setter方法从spring.xml获取它的条目,并在特定时间使用它。
答案 5 :(得分:0)
有一种情况,在OPTIONAL属性上使用@Autowired将无效。
如果你想使用该属性进行一些初始化,可能在调用构造函数之前没有设置它,并且因为它是可选的,所以你不能把它作为参数放在构造函数中。
在这种情况下,最好使用@Autowired setter方法,以便在属性自动装配后执行初始化。
答案 6 :(得分:0)
有3种自动装配类型:
@Autowired
private MyService service;
@Autowired
注释:class MyController {
private final MyService service;
public MyController(MyService service) {
this.service = service;
}
}
private MyService service;
@Autowired
public void setService(MyService service) {
this.service = service;
}
建议使用基于构造方法的,如果可能,则使用基于Setter的方法,最后使用基于Property的方法。
为什么?
首先,因为在基于Constructor的基础上,您甚至没有使用任何Spring注释。这可以帮助您过渡到不同的框架。
第二,基于构造函数或设置器,使单元测试更加容易。您不需要使用任何特定于Spring的测试工具,而只能使用Junit和Mockito。
第三,基于Constructor是好的,因为您可以将属性声明为final
,并且不公开setter,这有助于类的不变性和线程安全。