依赖注入的主要类型
- 构造器注入
- Setter注入
- 接口注入(不推荐)
- Filed变量注入(不推荐)
Setter注入 battle 构造器注入
-
构造器注入
Spring4.X以后鼓励使用构造器注入,构造器注入的组件通常需要在构造的时候完成初始化。即,一般依赖的组件以及组件依赖的外部输入等,都需要我们在构造的时候完成初始化。
实现业务组件时,如果该对象是一个不变的对象,构造器注入确保了这个对象不为空。即,当依赖一个对象时,这个对象必须存在,因此不能为空。哪怕这个对象不存在或者实在是为空的话,也可以通过ObjectProvider(Spring 4.X引入,一种类型安全的方式)的getIfAvailable()方法来进行返回。
-
构造器注入的优点:
- 构造器注入可以把一般都不会变更的字段,赋值的字段定义为final,无论是从线程安全的角度还是未来可变性的角度来说都是比较友好的。通常习惯在面向对象时,对象都是不变的,即一旦创建好就不要变,如果这个对象要变更,可以把这个对象重新生成一份,使用新生成的这个对象,而不是老的对象。
- 如果用多个Java Bean的时候,会减少一些代码,主要是指有Setter/getter方法。
- 构造器注入就有这个先后顺序的约束约束,一般就是根据Java语法就是谁在前,谁在后,进行初始化顺序的,不能由客户端任意修改。
-
构造器注入如果参数过多,代码看起来不是很友好,一般需要做一些重构,换句话说就是不应该把太多的职责放到一个类里,一个方法里不应该有太多的输入。
//构造器注入 private DependencyA dependencyA; private DependencyB dependencyB; private DependencyC dependencyC; @Autowired public DependencyInjection(DependencyA dependencyA, DependencyB dependencyB, DependencyC dependencyC) { this.dependencyA = dependencyA; this.dependencyB = dependencyB; this.dependencyC = dependencyC; }
-
Setter注入
Spring3.X鼓励使用,Spring 4.X以后认为是可选的注入方式,Setter注入字段本身是可变化的,所以对象本身或注入的内容可以为空。如@Autowired注解默认会把相关的依赖强行注入,如果依赖不存在,根据属性required(默认为true)设置为false来进行控制。
//不为age属性传递任何参数,下面的示例也会成功运行,但是name属性则需要一个参数 public class Student { private Integer age; private String name; @Autowired(required=false) public void SetAge(Integer age) { this.age = age; } @Autowired public void SetName(String name) { this.name = name; } }
Setter注入的优缺点
- Setter方法通常能够让对象变得更加可配置或者在某个时候可以被重新注入。换言之,依赖注入的时候,也许是第一次注入,那么是再次注入的话,也不会有一个新的对象的变化。
- Setter注入对具有默认值的对象非常有效,意味着并非所有属性都需要在运行时提供。对象里有个默认值,Setter方法可以覆盖掉这个初始值。
- Setter中的order无法确认,比如Student对象有个SetAge/SetName两个方法,至于哪个先,哪个后并没有一定的规约来进行约束。
- Setter的注入,只有当对象是需要被注入的时候它才会帮助我们注入依赖,而不是在初始化的时候就注入
//Setter注入 private DependencyA dependencyA; private DependencyB dependencyB; private DependencyC dependencyC; @Autowired public void setDependencyA(DependencyA dependencyA) { this.dependencyA = dependencyA; } @Autowired public void setDependencyB(DependencyB dependencyB) { this.dependencyB = dependencyB; } @Autowired(required=false) public void setDependencyC(DependencyC dependencyC) { this.dependencyC = dependencyC; }