spring @Autowire property vs setter

时间:2015-11-06 08:46:27

标签: java spring dependency-injection

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

7 个答案:

答案 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;
  • 基于构造函数。请注意,在这种情况下,在Spring Boot中甚至不需要@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,这有助于类的不变性和线程安全。