【设计模式】依赖注入
前言
依赖注入(Dependency Injection,DI)是控制反转原理(Inversion of Control,IoC)的实现方式之一。依赖注入在构建依赖项复杂且多的对象时,优势就很明显了,比如 Grafana 项目在构建 Service Graph 就用到了依赖注入,来梳理复杂的依赖图。
依赖注入
依赖注入对象与其依赖项的关联是通过装配器(Assembler)来完成,而不是对象自己创建依赖。
比如,一个传统的创建依赖对象的代码例子如下。Store 类的依赖对象 item 是类自己创建的。
public class Store {
private Item item;
public Store() {
item = new ItemImpl1();
}
}
利用依赖注入的思想,我们可以把上面代码改造如下。别看代码很普通、很习以为常。但确是实现了依赖注入,Store 类不再关心 item 对象的创建。最后,更高级的玩法是,通过一个依赖项的 metadata 配置信息或文件来创建对象,而不是直接传入一个实例。
public class Store {
private Item item;
public Store(Item item) {
this.item = item;
}
}
构造函数注入 vs Setter 方法注入
构造函数注入(Constructor-Based Dependency Injection,CDI)和 Setter 方法注入(Setter-Based Dependency Injection,SDI)是两种常见的依赖注入方式。两个 Java Spring 中的例子为例:
CDI 例子
代码:
package com.geeksforgeeks.org;
import com.geeksforgeeks.org.IGeek;
public class GFG {
// The object of the interface IGeek
IGeek geek;
// Constructor to set the CDI
GFG(IGeek geek)
{
this.geek = geek;
}
}
依赖项配置文件:
<beans
xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
<bean id="GFG" class="com.geeksforgeeks.org.GFG">
<constructor-arg>
<bean class="com.geeksforgeeks.org.impl.CsvGFG" />
</constructor-arg>
</bean>
<bean id="CsvGFG" class="com.geeksforgeeks.org.impl.CsvGFG" />
<bean id="JsonGFG" class="com.geeksforgeeks.org.impl.JsonGFG" />
</beans>
SDI 例子
代码:
package com.geeksforgeeks.org;
import com.geeksforgeeks.org.IGeek;
public class GFG {
// The object of the interface IGeek
IGeek geek;
// Setter method for property geek
public void setGeek(IGeek geek)
{
this.geek = geek;
}
}
依赖项配置文件:
<beans
xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
<bean id="GFG" class="com.geeksforgeeks.org.GFG">
<property name="geek">
<ref bean="CsvGFG" />
</property>
</bean>
<bean id="CsvGFG" class="com.geeksforgeeks.org.impl.CsvGFG" />
<bean id="JsonGFG" class="com.geeksforgeeks.org.impl.JsonGFG" />
</beans>
总结
依赖注入的概念其实很简单,具体运用起来有很多灵活的变式。
参考资料
[1] Intro to Inversion of Control and Dependency Injection with Spring
[2] Spring Dependency Injection with Example