解释为什么构造函数注入比其他选项更好

min*_*nil 63 java spring dependency-injection required

在Pro Spring 3 Book中,第4章 - 介绍IOC和DI在春天 - 第59页,在"Setter Injection vs. Constructor Injection"部分,一段说

包含Spring,提供了一种机制,用于确保在使用Setter Injection时定义所有依赖项,但是通过使用Constructor Injection,您可以以容器无关的方式声明对依赖项的要求"

你能解释一下例子吗?

Eme*_*gia 81

如果提供了该参数,则只能实例化一个必需的依赖项作为构造函数参数的类(您应该有一个guard子句以确保该参数不为null.)因此构造函数强制执行依赖性要求,无论您是否为使用Spring,使其与容器无关.

如果使用setter注入,则可能会调用或不调用setter,因此实例可能永远不会提供其依赖项.强制调用setter的唯一方法是使用@Requiredor @Autowired ,它特定于Spring,因此不是容器不可知的.

因此,为了保持代码独立于Spring,请使用构造函数参数进行注入.

更新:Spring 4.3将在单构造函数场景中执行隐式注入,使您的代码更加独立于Spring,可能根本不需要@Autowired注释.

  • @Addie 最引人注目的好处是它简化了测试。您可以在正常的单元测试中实例化该类(并传递构造函数参数,例如模拟),而无需配置应用程序上下文以及设置集成测试所带来的复杂性。 (2认同)

Mar*_*szS 16

(...)通过使用构造函数注入,您以容器无关的方式声明对依赖项的要求

这意味着你可以强制对所有注射领域的要求,而无需使用任何容器具体的解决方案.


塞特注射实例

使用setter注入时,需要特殊的弹簧注释@Required.

@需要

将方法(通常是JavaBean setter方法)标记为" required ":即,必须将setter方法配置为使用值依赖注入.

用法

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

import javax.inject.Inject;
import javax.inject.Named;

@Named
public class Foo {

    private Bar bar;

    @Inject
    @Required
    public void setBar(Bar bar) {
        this.bar = bar;
    }
}
Run Code Online (Sandbox Code Playgroud)

构造函数注入示例

所有必填字段都在构造函数,纯Java解决方案中定义.

用法

import javax.inject.Inject;
import javax.inject.Named;

@Named
public class Foo {

    private Bar bar;

    @Inject
    public Foo(Bar bar) {
        this.bar = bar;
    }

}
Run Code Online (Sandbox Code Playgroud)


Jaw*_*awa 11

为了简单起见,让我们说我们可以使用基于构造函数的依赖注入来实现强制依赖,并使用基于setter的注入来实现可选的依赖.这是一个经验法则!

比方说吧.

如果要实例化一个类,则始终使用其构造函数执行此操作.因此,如果您使用基于构造函数的注入,则实例化该类的唯一方法是通过该构造函数.如果通过构造函数传递依赖关系,那么很明显它是一个强制依赖.

另一方面,如果在POJO类中有setter方法,则可以使用该setter方法为类变量设置或不设置值.它完全基于您的需要.即它是可选的.因此,如果通过类的setter方法传递依赖关系,则隐式意味着它是一个可选的依赖项.希望这很清楚!!


vij*_*yst 5

如果没有依赖类,类无法运行,则使用构造函数注入.

当类可以在没有依赖类的情况下运行时,使用属性注入.

作为一个具体的例子,考虑一个依赖于IService来完成其工作的ServiceRepository.由于ServiceRepository在没有IService的情况下无法正常运行,因此通过构造函数注入它是有意义的.

同一个ServiceRepository类可以使用Logger进行跟踪.ILogger可以通过Property注入注入.

Property注入的其他常见示例是ICache(AOP术语中的另一个方面)或IBaseProperty(基类中的属性).


duf*_*ymo 0

有例子吗?这是一个简单的:

public class TwoInjectionStyles {
    private Foo foo;

    // Constructor injection
    public TwoInjectionStyles(Foo f) {
        this.foo = f;
    }

    // Setting injection
    public void setFoo(Foo f) { this.foo = f; }
}
Run Code Online (Sandbox Code Playgroud)

就我个人而言,如果可以的话,我更喜欢构造函数注入。

在这两种情况下,bean 工厂都会实例化TwoInjectionStylesFoo实例,并为前者提供Foo依赖关系。