Java spring @Autowire 属性与 setter
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/33562731/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
spring @Autowire property vs setter
提问by luso
What is the difference between anotate @Autowired to a property or do it in the setter?
将 @Autowired 注释到属性或在 setter 中执行有什么区别?
As far as I know they both have the same result, but is there any reason to use one over the other?
据我所知,它们都有相同的结果,但是有什么理由使用一个而不是另一个?
UPDATE (to be more concise)
更新(更简洁)
Is there a difference between this
这有区别吗
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();
}
}
and this
和这个
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();
}
}
采纳答案by SMA
With @Autowired
annotation, you don't need a setter method. Once your bean's constructor is done with allocating/creating the object, Spring will scan for this annotation and would inject the object instances that you annotated.
有了@Autowired
注解,你就不需要 setter 方法了。一旦 bean 的构造函数完成了对象的分配/创建,Spring 将扫描此注解并注入您注解的对象实例。
While if you have setter and if you are still using xml config, you would explicitly set properties.
而如果您有 setter 并且您仍在使用 xml 配置,则您将显式设置属性。
Having said that, You could annotate your constructor and setter method with autowired annotation which i would prefer as this would give me flexibility later on to move away from Spring (although i wont do it).
话虽如此,您可以使用自动装配的注释来注释您的构造函数和 setter 方法,这是我更喜欢的,因为这会给我以后远离 Spring 的灵活性(尽管我不会这样做)。
回答by Sarath Kumar Sivan
Autowiring works best when it is used consistently across a project. If autowiring is not used in general, it might be confusing to developers to use it to wire only one or two bean definitions. With @Autowired on a field you don't need a setter method, which, on one hand makes the class smaller and easier to read, but on the other hand makes mocking the class a bit uglier.
自动装配在整个项目中一致使用时效果最佳。如果通常不使用自动装配,开发人员可能会使用它来连接一两个 bean 定义,这可能会让人感到困惑。在字段上使用 @Autowired 时,您不需要 setter 方法,这一方面使类更小且更易于阅读,但另一方面使模拟类变得更难看。
Explicit dependencies in property and constructor-arg settings always override autowiring. You cannot autowire so-called simple properties such as primitives, Strings, and Classes (and arrays of such simple properties). This limitation is by-design.
属性和构造函数参数设置中的显式依赖项始终覆盖自动装配。您不能自动装配所谓的简单属性,例如基元、字符串和类(以及此类简单属性的数组)。此限制是有意设计的。
Autowiring is less exact than explicit wiring. Spring is careful to avoid guessing in case of ambiguity that might have unexpected results, the relationships between your Spring-managed objects are no longer documented explicitly.
自动装配不如显式装配精确。Spring 小心避免在可能产生意外结果的歧义的情况下进行猜测,不再明确记录 Spring 管理的对象之间的关系。
Wiring information may not be available to tools that may generate documentation from a Spring container.
可能无法从 Spring 容器生成文档的工具中使用接线信息。
Multiple bean definitions within the container may match the type specified by the setter method or constructor argument to be autowired. For arrays, collections, or Maps, this is not necessarily a problem. However for dependencies that expect a single value, this ambiguity is not arbitrarily resolved. If no unique bean definition is available, an exception is thrown.
容器内的多个 bean 定义可能与要自动装配的 setter 方法或构造函数参数指定的类型相匹配。对于数组、集合或映射,这不一定是问题。然而,对于期望单个值的依赖项,这种歧义不会被任意解决。如果没有唯一的 bean 定义可用,则抛出异常。
回答by maaartinus
If you can, you should avoid the setter. If you don't need it, it's better when it doesn't exists, right?
如果可以,您应该避免使用二传手。如果你不需要它,当它不存在时更好,对吧?
I personally prefer Guice allowing me to write
我个人更喜欢 Guice 允许我写
public class TextEditor {
private final SpellChecker spellChecker;
@Inject public TextEditor(SpellChecker spellChecker) {
this.spellChecker = spellChecker;
}
public void spellCheck(){
spellChecker.checkSpelling();
}
}
This goes a step further: With a final
field, I know it won't ever change and I get the multithreading visibility guarantee.
这更进一步:对于一个final
字段,我知道它永远不会改变并且我得到了多线程可见性保证。
回答by Bartosz Bilicki
Sometimes you need an instance of class A, but you do not store A in the fields of the class.
You just need A instance to perform a one-shot operation. Or, you use A instance to obtain an instance of B, and you are storing B in the field.
有时您需要类 A 的实例,但您没有将 A 存储在类的字段中。
你只需要一个实例来执行一次性操作。或者,您使用 A 实例获取 B 的实例,并将 B 存储在字段中。
In those cases, a setter (or constructor) autowire will suit you better.
You will not have unused class-level fields.
在这些情况下,setter(或构造函数)自动装配将更适合您。
您不会有未使用的类级别字段。
Concrete example:
You need to construct RabbitTemplate(an object that sends messages to RabbitMQ)
To construct it, you need 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-
具体例子:
你需要构造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-
You do not need to store that ConnectionFactory. In that case, code that looks like this:
您不需要存储该 ConnectionFactory。在这种情况下,代码如下所示:
Class MyClass {
private RabbitTemplate template;
@Autowired
void setConnectionFactory(ConnectionFactory c) {
template=new RabbitTemplate(c);
}
}
...will serve you better than directly autowiring the ConnectionFactoryfield.
...将比直接自动装配ConnectionFactory字段更好地为您服务。
In this example, autowiring at the constructor level would be even better, because your object will always be completely constructed. It will be clear that ConnectionFactoryis a mandatory dependency, not an optional one.
在此示例中,在构造函数级别自动装配会更好,因为您的对象将始终被完全构造。很明显ConnectionFactory是一个强制依赖项,而不是一个可选依赖项。
回答by Sahil Chhabra
If you use @Autowired
annotation on a property, spring will initiate the property using spring.xml. You don't need setter in this case.
如果在属性上使用@Autowired
注解,spring 将使用 spring.xml 启动该属性。在这种情况下,您不需要 setter。
If you use @Autowired
annotation on a setter, you are specifying to spring that it should initiate this property using this setter method where you can add your custom code, like initializing some other property with this property.
如果在setter上使用@Autowired
注解,则指定 spring 它应该使用此 setter 方法启动此属性,您可以在其中添加自定义代码,例如使用此属性初始化其他一些属性。
Usage with Example:In the case of using DAO operations using JdbcTemplate, you need DataSource as an input to JdbcTemplate, but DataSource is not required as a property in itself. So you can use DataSource Setter to initialize JdbcTempate by auto-wiring DataSource Setter. Please see the below code:
示例用法:在使用 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);
}
In the above code, the only use of dataSource was to get passed in JdbcTemplate. So, creating a property of dataSource doesn't make sense here. So, just use the @Autowired on setter method of DataSource bean to get its entry from spring.xml and make use of it at that particular time itself.
在上面的代码中,dataSource 的唯一用途是在 JdbcTemplate 中传递。因此,在这里创建 dataSource 的属性没有意义。因此,只需在 DataSource bean 的 setter 方法上使用 @Autowired 从 spring.xml 获取其条目并在特定时间使用它。
回答by AdamSkwersky
There is one case where using @Autowired on an OPTIONAL property would not work.
在一种情况下,在 OPTIONAL 属性上使用 @Autowired 不起作用。
If you want to do some initialization using that property, it might not be set before the constructor is called, and since it is optional, you cannot put it as an argument in the constructor.
如果您想使用该属性进行一些初始化,则可能不会在调用构造函数之前对其进行设置,并且由于它是可选的,因此您不能将其作为参数放入构造函数中。
In that case it is better to use an @Autowired setter method, so you can perform the initialization once the property is autowired.
在这种情况下,最好使用 @Autowired setter 方法,这样您就可以在属性自动装配后执行初始化。