您的位置:首页 > 其它

依赖注入(DI)的几种方式示例

2018-03-28 16:58 483 查看
因为本系列是为探究spring Ioc原理,故使用的spring版本为早期spring1.1.1版本,pom及相关依赖

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion>
<groupId>com.liusj</groupId>
<artifactId>springSource</artifactId>
<packaging>war</packaging>
<version>1.0-SNAPSHOT</version>
<name>springSource Maven Webapp</name>
<url>http://maven.apache.org</url>
<dependencies>

<!-- spring1.1.1 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring</artifactId>
<version>1.1.1</version>
</dependency>

<!-- log4j https://mvnrepository.com/artifact/org.apache.logging.log4j/log4j-api -->
<!-- https://mvnrepository.com/artifact/commons-logging/commons-logging -->
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.2</version>
</dependency>

<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>RELEASE</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>


四种依赖注入方式

Spring 依赖注入有四种方式:属性(setter)注入,构造器注入,静态工厂方法注入,实例工厂方法注入。最常见的是属性注入和构造器注入。下面对这几种注入方法举例说明:

属性(setter) 注入

<!-- setter-based dependency injection -->
<bean id="exampleBean" class="dependency_injection.ExampleBean">
<property name="beanOne"><ref bean="anotherBean"/></property>
<property name="beanTwo"><ref bean="yetAnotherBean"/></property>
<property name="integerProperty"><value>1</value></property>
</bean>

<bean id="anotherBean" class="dependency_injection.AnotherBean"/>
<bean id="yetAnotherBean" class="dependency_injection.YetAnotherBean"/>


构造器注入

<!-- constructor-based dependency injection -->
<bean id = "exampleBean1" class="dependency_injection.ExampleBean">
<constructor-arg index="0" type="dependency_injection.AnotherBean">
<ref bean="anotherBean"></ref>
</constructor-arg>
<constructor-arg>
<ref bean="yetAnotherBean"></ref>
</constructor-arg>
<constructor-arg>
<value>3</value>
</constructor-arg>
</bean>


静态工厂方法注入:

<!-- static factory method dependency injection-->
<bean id = "exampleBean2" class="dependency_injection.MyFactoryBean"
factory-method="getExampleBeanInstance">
</bean>
<bean id = "exampleBean3" class="dependency_injection.MyFactoryBean"
factory-method="getExampleBeanWithParamInstance">
<constructor-arg>
<ref bean="anotherBean"></ref>
</constructor-arg>
<constructor-arg>
<ref bean="yetAnotherBean"></ref>
</constructor-arg>
<constructor-arg>
<value>2</value>
</constructor-arg>
</bean>


实体工厂方法注入:

<!-- instance factory method dependency injection-->
<bean id="myfacotory" class="dependency_injection.MyFactoryBean"></bean>
<bean id="exampleBean4" factory-bean="myfacotory" factory-method="getExampleBean">
</bean>


上述类具体实现:

ExampleBean.java

package dependency_injection;

/**
* Created by Administrator on 2018/3/28 0028.
*/
public class ExampleBean {
private AnotherBean beanOne;
private YetAnotherBean beanTwo;
private String integerProperty;

public ExampleBean(){

}
public ExampleBean(AnotherBean anotherBean, YetAnotherBean yetAnotherBean,String integerProperty){
this.beanOne = anotherBean;
this.beanTwo = yetAnotherBean;
this.integerProperty = integerProperty;
}
public void setBeanOne(AnotherBean beanOne) {
this.beanOne = beanOne;
}

public AnotherBean getBeanOne() {
return beanOne;
}

public void setBeanTwo(YetAnotherBean beanTwo) {
this.beanTwo = beanTwo;
}

public YetAnotherBean getBeanTwo() {
return beanTwo;
}

public void setIntegerProperty(String integerProperty) {
this.integerProperty = integerProperty;
}

public String getIntegerProperty() {
return integerProperty;
}

}


AnotherBean.java

package dependency_injection;

/**
* Created by Administrator on 2018/3/28 0028.
*/
public class AnotherBean {
}


MyFactoryBean.java

package dependency_injection;

/**
* Created by Administrator on 2018/3/28 0028.
*/
public class MyFactoryBean {
public static ExampleBean exampleBean = null;

public static ExampleBean getExampleBeanInstance(){
if(exampleBean == null){
exampleBean = new ExampleBean();
return exampleBean;
} else {
return exampleBean;
}
}

public static ExampleBean getExampleBeanWithParamInstance(AnotherBean anotherBean, YetAnotherBean yetAnotherBean,String integerProperty){
if(exampleBean == null){
exampleBean = new ExampleBean();
exampleBean.setBeanOne(anotherBean);
exampleBean.setBeanTwo(yetAnotherBean);
exampleBean.setIntegerProperty(integerProperty);
return exampleBean;
} else {
return exampleBean;
}
}

public ExampleBean getExampleBean(){
return exampleBean;
}
}


YetAnotherBean.java

public class YetAnotherBean {
}


测试类 DI_Test.java

package dependency_injection;

import org.junit.Test;
import org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.core.io.ClassPathResource;

/**
* Created by Administrator on 2018/3/28 0028.
*/
public class DI_Test {
@Test
public void testSetterDI() {
ClassPathResource classPathResource = new ClassPathResource("di_beans.xml");
XmlBeanFactory xmlBeanFactory = new XmlBeanFactory(classPathResource);

// setter di
ExampleBean exampleBean = (ExampleBean) xmlBeanFactory.getBean("exampleBean");
System.out.println("exampleBean: " + exampleBean);
ExampleBean exampleBean_ = (ExampleBean) xmlBeanFactory.getBean("exampleBean");
System.out.println("exampleBean_: " + exampleBean_);
System.out.println("exampleBean == exampleBean_ " + (exampleBean == exampleBean_));

// constructor di
ExampleBean exampleBean1 = (ExampleBean) xmlBeanFactory.getBean("exampleBean1");
System.out.println("exampleBean1: " + exampleBean1);
ExampleBean exampleBean1_ = (ExampleBean) xmlBeanFactory.getBean("exampleBean1");
System.out.println("exampleBean1 == exampleBean1_ " + (exampleBean1 == exampleBean1_));

// static factory method di
ExampleBean exampleBean2 = (ExampleBean) xmlBeanFactory.getBean("exampleBean2");
System.out.println("exampleBean2: " + exampleBean2);
ExampleBean exampleBean3 = (ExampleBean) xmlBeanFactory.getBean("exampleBean3");
System.out.println("exampleBean3: " + exampleBean3);
System.out.println("exampleBean2 == exampleBean3 " + (exampleBean2 == exampleBean3));

// instance factory method di 实例工厂方法
ExampleBean exampleBean4 = (ExampleBean) xmlBeanFactory.getBean("exampleBean4");
System.out.println("exampleBean4: " + exampleBean4);
}
}


属性注入和构造器注入的优缺点

设值注入的优势

1. 对于习惯了传统JavaBean开发的程序员而言,通过setter方法设定依赖关系显得更加直

观,更加自然。

2. 如果依赖关系(或继承关系)较为复杂,那么Type3模式的构造函数也会相当庞大(我们需

要在构造函数中设定所有依赖关系),此时Type2模式往往更为简洁。

3. 对于某些第三方类库而言,可能要求我们的组件必须提供一个默认的构造函数(如Struts

中的Action),此时Type3类型的依赖注入机制就体现出其局限性,难以完成我们期望的功

能。

构造子注入的优势:

1. “在构造期即创建一个完整、合法的对象”,对于这条Java设计原则,Type3无疑是最好的

响应者。

2. 避免了繁琐的setter方法的编写,所有依赖关系均在构造函数中设定,依赖关系集中呈现,

更加易读。

3. 由于没有setter方法,依赖关系在构造时由容器一次性设定,因此组件在被创建之后即处于

相对“不变”的稳定状态,无需担心上层代码在调用过程中执行setter方法对组件依赖关系

产生破坏,特别是对于Singleton模式的组件而言,这可能对整个系统产生重大的影响。

4. 同样,由于关联关系仅在构造函数中表达,只有组件创建者需要关心组件内部的依赖关系。

对调用者而言,组件中的依赖关系处于黑盒之中。对上层屏蔽不必要的信息,也为系统的

层次清晰性提供了保证。

5. 通过构造子注入,意味着我们可以在构造函数中决定依赖关系的注入顺序,对于一个大量

依赖外部服务的组件而言,依赖关系的获得顺序可能非常重要,比如某个依赖关系注入的

先决条件是组件的DataSource及相关资源已经被设定。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: