学习spring容器IOC之依赖和依赖注入
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了学习spring容器IOC之依赖和依赖注入相关的知识,希望对你有一定的参考价值。
学习开涛跟我学spring3
http://jinnianshilongnian.iteye.com/
为什么要应用依赖注入,应用依赖注入能给我们带来哪些好处呢?
1.动态替换Bean依赖对象,程序更灵活:替换Bean依赖对象,无需修改源文件:应用依赖注入后,由于可以采用配置 文件方式实现,从而能随时动态的替换Bean的依赖对象,无需修改java源文件; 2.更好实践面向接口编程,代码更清晰:在Bean中只需指定依赖对象的接口,接口定义依赖对象完成的功能,通过容 器注入依赖实现; 3.更好实践优先使用对象组合,而不是类继承:因为IoC容器采用注入依赖,也就是组合对象,从而更好的实践对象组 合。
? 采用对象组合,Bean的功能可能由几个依赖Bean的功能组合而成,其Bean本身可能只提供少许功能或根本无任何功能,全部委托给依赖
Bean,对象组合具有动态性,能更方便的替换掉依赖Bean,从而改变Bean功能;
? 而如果采用类继承,Bean没有依赖Bean,而是采用继承方式添加新功能,,而且功能是在编译时就确定了,不具有动态性,而且采用类继
承导致Bean与子Bean之间高度耦合,难以复用。
3.1代码结构如下
3.1构造器注入
HelloImpl代码如下
package com.springframe.springstudy.chapter3; import com.springframe.springstudy.HelloApi; public class HelloImpl implements HelloApi { private String message; private int index; public HelloImpl(String message, int index) { this.message = message; this.index = index; } public HelloImpl(){ } @Override public void sayHello() { System.out.printf("helloImpl1:(message:"+this.message+",index:"+this.index+")"); } }
helloword.xml代码如下
<?xml version="1.0" encoding="UTF-8"?> <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.xsd"> <!-- 通过构造器参数索引方式依赖注入--> <bean id="byIndex" class="com.springframe.springstudy.chapter3.HelloImpl"> <constructor-arg index="0" value="Hello World!"/> <constructor-arg index="1" value="1"/> </bean> <!-- 通过构造器参数类型方式依赖注入--> <bean id="byType" class="com.springframe.springstudy.chapter3.HelloImpl"> <constructor-arg type="java.lang.String" value="Hello World!"/> <constructor-arg type="int" value="2"/> </bean> <!-- 通过构造器参数名称方式依赖注入--> <bean id="byName" class="com.springframe.springstudy.chapter3.HelloImpl"> <constructor-arg name="message" value="Hello World!"/> <constructor-arg name="index" value="3"/> </bean> </beans>
HelloImplTest测试代码如下
package com.springframe.springstudy.chapter3; import com.springframe.springstudy.HelloApi; import org.junit.Test; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; @SpringBootTest public class HelloImplTest { @Test public void test() { ApplicationContext context = new ClassPathXmlApplicationContext("chapter3/helloword.xml"); HelloApi index = context.getBean("byIndex", HelloApi.class); HelloApi type = context.getBean("byType", HelloApi.class); HelloApi name = context.getBean("byName", HelloApi.class); index.sayHello(); type.sayHello(); name.sayHello(); } }
测试结果如下:
3.2讲解
1.、根据参数索引注入,使用标签
<constructor-arg index="1" value="1"/> ,index值1,代码构造器参数的索引位置(从0开始),value代表需要注入的值.
2.根据参数类型进行注入,使用标签
<constructor-arg type="int" value="2"/>,type的值代表参数的类型,value代表需要注入的值
3.根据参数名进行注入,使用标签“<constructor-arg name="message" value="Hello World!"/>”来指定注入
的依赖,其中“name”表示需要匹配的参数名字,“value”来指定注入的常量值,
3.3使用静态工厂注入
在HelloImpl加上以下代码
public static HelloApi newInstance(String message,int index){ return new HelloImpl(message,index); }
在helloword.xml加上以下代码
<!-- 通过 静态工厂 构造器参数索引方式依赖注入--> <bean id="byIndexFactory" class="com.springframe.springstudy.chapter3.HelloImpl" factory-method="newInstance"> <constructor-arg index="0" value="Hello World! byIndexFactory"/> <constructor-arg index="1" value="1"/> </bean>
然后进行测试
@Test public void testFactory() { ApplicationContext context = new ClassPathXmlApplicationContext("chapter3/helloword.xml"); HelloApi indexFactory = context.getBean("byIndexFactory", HelloApi.class); indexFactory.sayHello(); }
3.4通过setter方法注入
在helloword.xml加上以下代码(需要在HelloImpl中未index,message,写入setter方法)
<!-- 通过 setter 构造器参数索引方式依赖注入--> <bean id="byIndexSetter" class="com.springframe.springstudy.chapter3.HelloImpl" > <property name="index" value="2"/> <property name="message" value="Hello World! setter"/> </bean>
进行测试
@Test public void testSetter() { ApplicationContext context = new ClassPathXmlApplicationContext("chapter3/helloword.xml"); HelloApi indexFactory = context.getBean("byIndexSetter", HelloApi.class); indexFactory.sayHello(); }
3.5 注入集合、数组和字典
Spring不仅能注入简单类型数据,还能注入集合(Collection、无序集合Set、有序集合List)类型、数组(Array)类
型、字典(Map)类型数据、Properties类型数据
1、注入集合类型:包括Collection类型、Set类型、List类型数据
集合list注入:
HelloImpl代码
package com.springframe.springstudy.chapter3; import com.springframe.springstudy.HelloApi; import java.util.Arrays; import java.util.List; public class HelloImpl implements HelloApi { private String message; private int index; private List<String> list; public HelloImpl(String message, int index) { this.message = message; this.index = index; } public HelloImpl(){ } public static HelloApi newInstance(String message,int index){ return new HelloImpl(message,index); } @Override public void sayHello() { System.out.println("helloImpl1:(message:"+this.message+",index:"+this.index+",list:"+ this.list+")"); } public void setMessage(String message) { this.message = message; } public void setIndex(int index) { this.index = index; } public void setList(List<String> list) { this.list = list; } }
helloword.xml代码
<?xml version="1.0" encoding="UTF-8"?> <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.xsd"> <!-- 通过构造器参数索引方式依赖注入--> <bean id="byIndex" class="com.springframe.springstudy.chapter3.HelloImpl"> <constructor-arg index="0" value="Hello World!"/> <constructor-arg index="1" value="1"/> </bean> <!-- 通过构造器参数类型方式依赖注入--> <bean id="byType" class="com.springframe.springstudy.chapter3.HelloImpl"> <constructor-arg type="java.lang.String" value="Hello World!"/> <constructor-arg type="int" value="2"/> </bean> <!-- 通过构造器参数名称方式依赖注入--> <bean id="byName" class="com.springframe.springstudy.chapter3.HelloImpl"> <constructor-arg name="message" value="Hello World!"/> <constructor-arg name="index" value="3"/> </bean> <!-- 通过 静态工厂 构造器参数索引方式依赖注入--> <bean id="byIndexFactory" class="com.springframe.springstudy.chapter3.HelloImpl" factory-method="newInstance"> <constructor-arg index="0" value="Hello World! byIndexFactory"/> <constructor-arg index="1" value="1"/> </bean> <!-- 通过 setter 构造器参数索引方式依赖注入--> <bean id="byIndexSetter" class="com.springframe.springstudy.chapter3.HelloImpl"> <property name="index" value="2"/> <property name="message" value="Hello World! setter"/> <property name="list"> <list> <value>1</value> <value>2</value> <value>3</value> </list> </property> </bean> </beans>
测试代码
@Test
public void testSetter() {
ApplicationContext context = new ClassPathXmlApplicationContext("chapter3/helloword.xml");
HelloApi indexFactory = context.getBean("byIndexSetter", HelloApi.class);
indexFactory.sayHello();
}
测试结果
set类型(HelloImpl类中加入属性:
private Collection<String> values;并写入对应的setter方法
)
<!-- 通过 setter 构造器参数索引方式依赖注入--> <bean id="byIndexSetter" class="com.springframe.springstudy.chapter3.HelloImpl"> <property name="index" value="2"/> <property name="message" value="Hello World! setter"/> <property name="list"> <list> <value>1</value> <value>2</value> <value>3</value> </list> </property> <property name="values"> <set> <value>a</value> <value>b</value> <value>c</value> </set> </property> </bean>
2.注入数组
HelloImpl配置属性:private String[] array;并对应的setter方法
<!-- 通过 setter 构造器参数索引方式依赖注入--> <bean id="byIndexSetter" class="com.springframe.springstudy.chapter3.HelloImpl"> <property name="index" value="2"/> <property name="message" value="Hello World! setter"/> <property name="list"> <list> <value>1</value> <value>2</value> <value>3</value> </list> </property> <property name="values"> <set> <value>a</value> <value>b</value> <value>c</value> </set> </property> <property name="array"> <array> <value>array1</value> <value>array2</value> </array> </property> </bean>
3.map注入
<!-- 通过 setter 构造器参数索引方式依赖注入--> <bean id="byIndexSetter" class="com.springframe.springstudy.chapter3.HelloImpl"> <property name="index" value="2"/> <property name="message" value="Hello World! setter"/> <property name="list"> <list> <value>1</value> <value>2</value> <value>3</value> </list> </property> <property name="values"> <set> <value>a</value> <value>b</value> <value>c</value> </set> </property> <property name="array"> <array> <value>array1</value> <value>array2</value> </array> </property> <property name="map"> <map> <entry> <key><value>1</value></key> <value>1</value> </entry> <entry> <key><value>2</value></key> <value>2</value> </entry> </map> </property> </bean>
4.properties注入
<!-- 通过 setter 构造器参数索引方式依赖注入--> <bean id="byIndexSetter" class="com.springframe.springstudy.chapter3.HelloImpl"> <property name="index" value="2"/> <property name="message" value="Hello World! setter"/> <property name="list"> <list> <value>1</value> <value>2</value> <value>3</value> </list> </property> <property name="values"> <set> <value>a</value> <value>b</value> <value>c</value> </set> </property> <property name="array"> <array> <value>array1</value> <value>array2</value> </array> </property> <property name="map"> <map> <entry> <key><value>1</value></key> <value>1</value> </entry> <entry> <key><value>2</value></key> <value>2</value> </entry> </map> </property> <property name="properties"> <props> <prop key="key">key</prop> <prop key="key1">key1</prop> </props> </property> </bean>
5.引用其他的bean
用ref 标签
<bean name="test" class="java.lang.String"> <constructor-arg index="0" value="1111"/> </bean> <!-- 通过 setter 构造器参数索引方式依赖注入--> <bean id="byIndexSetter" class="com.springframe.springstudy.chapter3.HelloImpl"> <property name="index" value="2"/> <property name="message" value="Hello World! setter"/> <property name="list"> <list> <ref bean="test"/> <value>2</value> <value>3</value> </list> </property> <property name="values"> <set> <value>a</value> <value>b</value> <value>c</value> </set> </property> <property name="array"> <array> <value>array1</value> <value>array2</value> </array> </property> <property name="map"> <map> <entry> <key><value>1</value></key> <value>1</value> </entry> <entry> <key><value>2</value></key> <value>2</value> </entry> </map> </property> <property name="properties"> <props> <prop key="key">key</prop> <prop key="key1">key1</prop> </props> </property> </bean>
6.注入null值
<property name="properties"><null></null> </property>
一、构造器注入:
1)常量值
简写:<constructor-arg index="0" value="常量"/>
全写:<constructor-arg index="0"><value>常量</value></constructor-arg>
2)引用
简写:<constructor-arg index="0" ref="引用"/>
全写:<constructor-arg index="0"><ref bean="引用"/></constructor-arg>
二、setter注入:
1)常量值
简写:<property name="message" value="常量"/>
全写:<property name="message"><value>常量</value></ property>
2)引用
简写:<property name="message" ref="引用"/>
全写:<property name="message"><ref bean="引用"/></ property>
3)数组:<array>没有简写形式
4)列表:<list>没有简写形式
5)集合:<set>没有简写形式
6)字典
简写:<map>
<entry key="键常量" value="值常量"/>
<entry key-ref="键引用" value-ref="值引用"/>
</map>
全写:<map>
<entry><key><value>键常量</value></key><value>值常量</value></entry>
http://jinnianshilongnian.iteye.com 1.4 【第三章】 DI 之 3.1 DI的配置使用 ——跟我学spring3
第 62 / 366 页
<entry><key><ref bean="键引用"/></key><ref bean="值引用"/></entry>
</map>
7)Properties:没有简写形式
延迟初始化Bean
延迟初始化也叫做惰性初始化,指不提前初始化Bean,而是只有在真正使用时才创建及初始化Bean。
配置方式很简单只需在<bean>标签上指定 “lazy-init” 属性值为“true”即可延迟初始化Bean。
Spring容器会在创建容器时提前初始化“singleton”作用域的Bean,“singleton”就是单例的意思即整个容器
每个Bean只有一个实例,后边会详细介绍。Spring容器预先初始化Bean通常能帮助我们提前发现配置错误,所以如果
没有什么情况建议开启,除非有某个Bean可能需要加载很大资源,而且很可能在整个应用程序生命周期中很可能使用不
到,可以设置为延迟初始化。
延迟初始化的Bean通常会在第一次使用时被初始化;或者在被非延迟初始化Bean作为依赖对象注入时在会随着初
始化该Bean时被初始化,因为在这时使用了延迟初始化Bean。
容器管理初始化Bean消除了编程实现延迟初始化,完全由容器控制,只需在需要延迟初始化的Bean定义上配置即
可,比编程方式更简单,而且是无侵入代码的。
<bean id="helloApi" class="cn.javass.spring.chapter2.helloworld.HelloImpl" lazy-init="true"/>
使用depends-on
depends-on是指指定Bean初始化及销毁时的顺序,使用depends-on属性指定的Bean要先初始化完毕后才初始
化当前Bean,由于只有“singleton”Bean能被Spring管理销毁,所以当指定的Bean都是“singleton”时,使用
depends-on属性指定的Bean要在指定的Bean之后销毁。
<bean id="helloApi" class="cn.javass.spring.chapter2.helloworld.HelloImpl"/> <bean id="decorator" class="cn.javass.spring.chapter3.bean.HelloApiDecorator" depends-on="helloApi"> <property name="helloApi"><ref bean="helloApi"/></property> </bean>
那“depends-on”有什么好处呢?主要是给出明确的初始化及销毁顺序,比如要初始化“decorator”时要确保
“helloApi”Bean的资源准备好了,否则使用“decorator”时会看不到准备的资源;而在销毁时要先在
“decorator”Bean的把对“helloApi”资源的引用释放掉才能销毁“helloApi”,否则可能销毁 “helloApi”时而
“decorator”还保持着资源访问,造成资源不能释放或释放错误
自动装配
自动装配就是指由Spring来自动地注入依赖对象,无需人工参与。
目前Spring3.0支持“no”、“byName ”、“byType”、“constructor”四种自动装配,默认是“no”指不支
持自动装配的,其中Spring3.0已不推荐使用之前版本的“autodetect”自动装配,推荐使用Java 5+支持的
(@Autowired)注解方式代替;如果想支持“autodetect”自动装配,请将schema改为“spring-beans-2.5.xsd”
或去掉。
自动装配的好处是减少构造器注入和setter注入配置,减少配置文件的长度。自动装配通过配置<bean>标签的
“autowire”属性来改变自动装配方式。接下来让我们挨着看下配置的含义。
一、default:表示使用默认的自动装配,默认的自动装配需要在<beans>标签中使用default-autowire属性指
定,其支持“no”、“byName ”、“byType”、“constructor”四种自动装配,如果需要覆盖默认自动装配
基本的作用域
一、singleton:指“singleton”作用域的Bean只会在每个Spring IoC容器中存在一个实例,而且其完整生命
周期完全由Spring容器管理。对于所有获取该Bean的操作Spring容器将只返回同一个Bean。
以上是关于学习spring容器IOC之依赖和依赖注入的主要内容,如果未能解决你的问题,请参考以下文章