依赖注入(DI)的几种方式示例
2018-03-28 16:58
483 查看
因为本系列是为探究spring Ioc原理,故使用的spring版本为早期spring1.1.1版本,pom及相关依赖
属性(setter) 注入
构造器注入
静态工厂方法注入:
实体工厂方法注入:
上述类具体实现:
ExampleBean.java
AnotherBean.java
MyFactoryBean.java
YetAnotherBean.java
测试类 DI_Test.java
1. 对于习惯了传统JavaBean开发的程序员而言,通过setter方法设定依赖关系显得更加直
观,更加自然。
2. 如果依赖关系(或继承关系)较为复杂,那么Type3模式的构造函数也会相当庞大(我们需
要在构造函数中设定所有依赖关系),此时Type2模式往往更为简洁。
3. 对于某些第三方类库而言,可能要求我们的组件必须提供一个默认的构造函数(如Struts
中的Action),此时Type3类型的依赖注入机制就体现出其局限性,难以完成我们期望的功
能。
构造子注入的优势:
1. “在构造期即创建一个完整、合法的对象”,对于这条Java设计原则,Type3无疑是最好的
响应者。
2. 避免了繁琐的setter方法的编写,所有依赖关系均在构造函数中设定,依赖关系集中呈现,
更加易读。
3. 由于没有setter方法,依赖关系在构造时由容器一次性设定,因此组件在被创建之后即处于
相对“不变”的稳定状态,无需担心上层代码在调用过程中执行setter方法对组件依赖关系
产生破坏,特别是对于Singleton模式的组件而言,这可能对整个系统产生重大的影响。
4. 同样,由于关联关系仅在构造函数中表达,只有组件创建者需要关心组件内部的依赖关系。
对调用者而言,组件中的依赖关系处于黑盒之中。对上层屏蔽不必要的信息,也为系统的
层次清晰性提供了保证。
5. 通过构造子注入,意味着我们可以在构造函数中决定依赖关系的注入顺序,对于一个大量
依赖外部服务的组件而言,依赖关系的获得顺序可能非常重要,比如某个依赖关系注入的
先决条件是组件的DataSource及相关资源已经被设定。
<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及相关资源已经被设定。
相关文章推荐
- 关于Spring依赖注入的几种方式
- Spring的依赖注入(DI)三种方式
- Spring Ioc-依赖注入的几种方式
- spring学习笔记(1)-spring依赖注入的几种方式
- Spring 依赖注入的几种方式详解
- SpringIOC容器创建对象及依赖注入的几种方式
- spring学习总结(三):IOC & DI 配置 Bean 之配置形式及依赖注入方式
- Spring 常用的几种依赖注入方式
- Spring 常用的几种依赖注入方式
- Spring Ioc-依赖注入的几种方式
- spring的依赖注入几种方式
- spring ioc容器注入的集中方式,以及属性注入的集中依赖,继承,使用SPEL表达式,ioc容器的生命周期,bean的几种工厂方法配置方式,bean的自动装配
- 峰Spring4学习(2)依赖注入的几种方式
- spring IOC(控制反转)和DI(依赖注入)以及三种依赖注入方式的比较
- spring详解:spring IOC依赖注入的几种方式
- Spring依赖注入的几种实现方式
- IOC与DI的讲解以及依赖注入的三种方式
- Spring Ioc 之二 -依赖注入的几种方式
- Spring Ioc-依赖注入的几种方式
- 解释spring的ioc? 几种注入依赖的方式?spring的优点?