Field injection is not recommended(不再推荐使用字段注入)
- 1.依赖注入的类型有3种
- 1.1基于构造函数的依赖注入
- 1.2基于Setter的依赖注入
- 1.3基于属性的依赖注入
- 2.基于字段的依赖注入缺陷
- 不允许声明不可变域
- 容易违反单一职责设计原则
- 与依赖注入容器紧密耦合
- 隐藏依赖关系
- 3.总结
spring framerwork 4.0以后开始出现的,spring 4.0开始就不推荐使用属性注入,改为推荐构造器注入和setter注入。
1.依赖注入的类型有3种
1.1基于构造函数的依赖注入
@Autowired注解也是可以省去的。
public class SimpleMovieLister {
// the SimpleMovieLister has a dependency on a MovieFinder
private final MovieFinder movieFinder;
// a constructor so that the Spring can inject a MovieFinder
public SimpleMovieLister(MovieFinder movieFinder) {
this.movieFinder = movieFinder;
}
// business logic that actually uses the injected MovieFinder is omitted...
}
基于构造函数注入的主要优点是可以将需要注入的字段声明为final, 使得它们会在类实例化期间被初始化,这对于所需的依赖项很方便。
1.2基于Setter的依赖注入
@Autowired注解也是可以省去的。在基于setter的依赖注入中,setter方法被标注为@Autowired。一旦使用无参数构造函数或无参数静态工厂方法实例化Bean,为了注入Bean的依赖项,Spring容器将调用这些setter方法。
public class SimpleMovieLister {
// the SimpleMovieLister has a dependency on the MovieFinder
private MovieFinder movieFinder;
// a setter method so that the Spring can inject a MovieFinder
@Autowired
public void setMovieFinder(MovieFinder movieFinder) {
this.movieFinder = movieFinder;
}
// business logic that actually uses the injected MovieFinder is omitted...
}
1.3基于属性的依赖注入
@Component
public class FieldBasedInjection {
@Autowired
private InjectedBean injectedBean;
}
正如所看到的,这是依赖注入最干净的方法,因为它避免了添加样板代码,并且不需要声明类的构造函数。代码看起来很干净简洁,但是正如代码检查器已经向我们暗示的那样,这种方法有一些缺点。
2.基于字段的依赖注入缺陷
不允许声明不可变域
基于字段的依赖注入在声明为final/immutable的字段上不起作用,因为这些字段必须在类实例化时实例化。声明不可变依赖项的惟一方法是使用基于构造器的依赖注入。
容易违反单一职责设计原则
尽管属性注入并不是破坏单一责任原则的直接原因,但它隐藏了信号,使我们很容易忽略这些信号。
与依赖注入容器紧密耦合
如果您想在应用程序容器之外使用您的类,例如用于单元测试,您将被迫使用Spring容器来实例化您的类,因为没有其他可能的方法(除了反射)来设置自动装配字段。
隐藏依赖关系
在使用依赖注入时,受影响的类应该使用公共接口清楚地公开这些依赖项,方法是在构造函数中公开所需的依赖项,或者使用方法(setter)公开可选的依赖项。当使用基于字段的依赖注入时,实质上是将这些依赖对外隐藏了。
3.总结
我们已经看到,基于字段的注入应该尽可能地避免,因为它有许多缺点,无论它看起来多么优雅。推荐的方法是使用基于构造函数和基于setter的依赖注入。对于必需的依赖,建议使用基于构造函数的注入,设置它们为不可变的,并防止它们为null。对于可选的依赖项,建议使用基于sett的注入。