文章目录
- 一、说明
- 二、构造函数注入
- 2.1、方式一【index索引方式】
- 2.1.1、定义Bean
- 2.1.2、主配置文件中配置Bean
- 2.1.3、测试
- 2.2、方式二【index+type组合方式】
- 2.2.1、定义Bean
- 2.2.2、主配置文件配置Bean
- 2.2.3、测试
- 2.2.4、解决方案
- 2.3、方式三【name方式】
- 2.3.1、定义Bean
- 2.3.2、主配置文件配置Bean
- 2.3.3、测试
- 2.4、补充细节
- 2.4.1、定义Bean
- 2.4.2、主配置文件配置Bean
- 2.4.3、测试
- 2.4.4、解决方案
- 2.5、总结
- 三、set方法注入
- 3.1、定义Bean
- 3.2、主配置文件配置Bean
- 3.3、测试
- 3.4、总结
- 四、复杂类型的注入
- 4.1、注入数组类型【array】
- 4.1.1、定义Bean
- 4.1.2、主配置文件配置Bean
- 4.2、注入List类型【list】
- 4.2.1、定义Bean
- 4.2.2、主配置文件配置Bean
- 4.3、注入Set类型【set】
- 4.3.1、定义Bean
- 4.3.2、主配置文件配置Bean
- 4.4、注入Map类型【Map】
- 4.4.1、定义Bean
- 4.4.2、主配置文件配置Bean
- 4.5、注入Properties类型
- 4.5.1、定义Bean
- 4.5.2、主配置文件配置Bean
- 4.6、总结
- 好书推荐
- 送书活动
一、说明
-
全称
Dependency Injection(DI)
-
与IoC的关系
IoC和DI其实说的是一个意思,可以这么说:IoC是一种思想,DI是对这种思想的一种具体实现
- 依赖关系的管理
以后都交给spring来维护,在当前类需要用到其他类的对象,由spring为我们提供,我们只需要在配置文件中说明。
-
依赖关系的维护
称之为依赖注入。
-
能注入的数据:有三类
基本类型和String。
其他bean类型(在配置文件中或者注解配置过的bean)
复杂类型/集合类型
-
注入的方式:有三种
第一种:使用构造函数提供
第二种:使用set方法提供
第三种:使用注解提供(参考第七章节)
二、构造函数注入
2.1、方式一【index索引方式】
2.1.1、定义Bean
public class Person {
private Integer id;
private String name; // 姓名
private Integer age; // 年龄
private Double weight; // 体重
public Person(Integer id, String name, Integer age) {
this.id = id;
this.name = name;
this.age = age;
}
}
2.1.2、主配置文件中配置Bean
<beans>
<bean id="person" class="cn.bdqn.Person">
<constructor-arg index="0" value="1" />
<constructor-arg index="1" value="王浩"/>
<constructor-arg index="2" value="20"/>
</bean>
</beans>
2.1.3、测试
@Test
public void testPerson() throws Exception{
// 1、读取主配置文件信息,获取核心容器对象
ApplicationContext ac = new ClassPathXmlApplicationContext("beans.xml");
Person person = (Person) ac.getBean("person");
System.out.println(person); // Person{id=1, name='王浩', age=20}
}
2.2、方式二【index+type组合方式】
说明:案例1采用的index索引的方式实现注入,就以目前案例来说是完全没问题的,但是如果Bean中存在下面情况,可能就不怎么适用了。
需求:我现在要创建Person类的对象,调用Person(Integer id, String name, Double weight)构造方法
2.2.1、定义Bean
说明:为Person类中的weight属性初始化,并专门为其添加构造方法
public class Person {
private Integer id;
private String name; // 姓名
private Integer age; // 年龄
private Double weight; // 体重
public Person(Integer id, String name, Integer age) {
this.id = id;
this.name = name;
this.age = age;
}
// 专门为weight属性定义的构造方法
public Person(Integer id, String name, Double weight) {
this.id = id;
this.name = name;
this.weight = weight;
}
}
2.2.2、主配置文件配置Bean
<beans>
<bean id="person" class="cn.bdqn.Person">
<constructor-arg index="0" value="1" />
<constructor-arg index="1" value="王浩"/>
<constructor-arg index="2" value="180"/>
</bean>
</beans>
2.2.3、测试
@Test
public void testPerson() throws Exception{
// 1、读取主配置文件信息,获取核心容器对象
ApplicationContext ac = new ClassPathXmlApplicationContext("beans.xml");
Person person = (Person) ac.getBean("person");
System.out.println(person); // Person{id=1, name='王浩', age=180}
}
经过测试发现,并不满足我的需求,还是找的是public Person(Integer id, String name, Integer age)构造方法
2.2.4、解决方案
通过type明确指定类型。
<bean>
<bean id="person" class="cn.bdqn.Person">
<constructor-arg index="0" type="java.lang.Integer" value="1" />
<constructor-arg index="1" type="java.lang.String" value="王浩"/>
<constructor-arg index="2" type="java.lang.Double" value="180"/>
</bean>
</bean>
2.3、方式三【name方式】
前两种方式通过index+type的确可以解决问题,但是总是觉得还是有些麻烦,能否有更加简单的方式呢?就是直接采用参数名的方式更易于阅读和使用。
2.3.1、定义Bean
Bean的定义同2.2.1。
2.3.2、主配置文件配置Bean
<beans>
<bean id="person" class="cn.bdqn.Person">
<constructor-arg name="id" value="2"/>
<constructor-arg name="name" value="史周冲"/>
<constructor-arg name="age" value="3"/>
</bean>
</beans>
2.3.3、测试
@Test
public void testPerson() throws Exception{
// 1、读取主配置文件信息,获取核心容器对象
ApplicationContext ac = new ClassPathXmlApplicationContext("beans.xml");
Person person = (Person) ac.getBean("person");
System.out.println(person); // Person{id=1, name='王浩', age=3}
}
2.4、补充细节
2.4.1、定义Bean
public class Person {
private Integer id;
private String name; // 姓名
private Date birthday; // 出生日期
public Person(Integer id, String name, Date birthday) {
this.id = id;
this.name = name;
this.birthday = birthday;
}
}
2.4.2、主配置文件配置Bean
<beans>
<bean id="person" class="cn.bdqn.Person">
<constructor-arg name="id" value="2"/>
<constructor-arg name="name" value="史周冲"/>
<constructor-arg name="birthday" value="2019-09-09" />
</bean>
</beans>
2.4.3、测试
测试后发现程序报错,原因在于:期望需要一个Date类型,而你现在传了一个字符串,数据类型不匹配。
Unsatisfied dependency expressed through constructor parameter 2: Could not convert argument value of type [java.lang.String] to required type [java.util.Date]
2.4.4、解决方案
<beans>
<bean id="person" class="cn.bdqn.Person">
<constructor-arg name="id" value="2"/>
<constructor-arg name="name" value="史周冲"/>
<!-- 注意:用了ref属性-->
<constructor-arg name="birthday" ref="currentDate"/>
</bean>
<!-- 定义日期Bean,Spring就会帮助我们new一个Date对象-->
<bean id="currentDate" class="java.util.Date"/>
</beans>
2.5、总结
-
使用的标签:
constructor-arg
-
标签出现的位置:
bean标签的内部
-
标签中的属性:
type:用于指定要注入的数据的数据类型。
index:用于指定要注入的数据给构造函数中指定索引位置的参数赋值,索引的位置是从0开始。
name:用于指定给构造函数中指定名称的参数赋值。
value:用于提供基本类型和String类型的数据。
ref:引用,用于指定其他的bean类型数据。它指的就是在spring的Ioc核心容器中出现过的bean对象。
-
优势:
假设我们需要创建一个对象时,需要明确初始化一些数据,那么这种方式显然是很好的。因为通过构造函数创建对象时候,如果不指定具体的参数是无法把对象创建成功的。可以起到一个约束的作用。
-
劣势:
改变了bean对象的实例化方式,使我们在创建对象时,如果用不到这些数据,也必须提供。
三、set方法注入
3.1、定义Bean
public class User {
private String name;
private Date born;
public void setName(String name) {
this.name = name;
}
public void setBorn(Date born) {
this.born = born;
}
}
说明:set注入方式不必生成get方法
3.2、主配置文件配置Bean
<bean id="currentDate" class="java.util.Date"/>
<bean id="user" class="cn.bdqn.User">
<property name="name" value="宋炜烨"/>
<property name="born" ref="currentDate"/>
</bean>
3.3、测试
@Test
public void testUser() throws Exception{
// 1、读取主配置文件信息,获取核心容器对象
ApplicationContext ac = new ClassPathXmlApplicationContext("beans.xml");
User user = (User) ac.getBean("user");
System.out.println(user); // User{name='宋炜烨', born=Thu Nov 14 22:29:11 CST 2019}
}
3.4、总结
-
涉及的标签
property
-
出现的位置
bean标签的内部
-
标签的属性
name:用于指定注入时所调用的set方法名称。
value:用于提供基本类型和String类型的数据。
ref:用于指定其他的bean类型数据。它指的就是在spring的Ioc核心容器中出现过的bean对象。
-
优势
创建对象时没有明确的限制,可以直接使用默认构造函数。
-
劣势
如果有某个成员属性必须有值,则有可能再使用该对象的时候并没有通过set方法注入值,可能拿到为空的值。
四、复杂类型的注入
4.1、注入数组类型【array】
4.1.1、定义Bean
public class Cat {
private String[] arrs;
public void setArrs(String[] arrs) {
this.arrs = arrs;
}
}
4.1.2、主配置文件配置Bean
<beans>
<bean id="cat" class="cn.bdqn.Cat">
<property name="arrs">
<array>
<value>崔灿</value>
<value>时贝妮</value>
</array>
</property>
</bean>
</beans>
4.2、注入List类型【list】
4.2.1、定义Bean
public class Cat {
private List<String> arrList;
public void setArrList(List<String> arrList) {
this.arrList = arrList;
}
}
4.2.2、主配置文件配置Bean
<beans>
<bean id="cat" class="cn.bdqn.Cat">
<property name="arrList">
<list>
<value>乔峰</value>
<value>马夫人</value>
</list>
</property>
</bean>
</beans>
4.3、注入Set类型【set】
4.3.1、定义Bean
public class Cat {
private Set<String> arrSet;
public void setArrSet(Set<String> arrSet) {
this.arrSet = arrSet;
}
}
4.3.2、主配置文件配置Bean
<beans>
<bean id="cat" class="cn.bdqn.Cat">
<property name="arrSet">
<set>
<value>段誉</value>
<value>鸠摩智</value>
</set>
</property>
</bean>
</beans>
4.4、注入Map类型【Map】
4.4.1、定义Bean
public class Cat {
private Map<String,Object> arrMap;
public void setArrMap(Map<String, Object> arrMap) {
this.arrMap = arrMap;
}
}
4.4.2、主配置文件配置Bean
<bean>
<property name="arrMap">
<map>
<entry key="S001" value="彭依凝"/>
<entry key="S002" value="段康家"/>
<entry key="S003" value="王浩"/>
</map>
</property>
</bean>
4.5、注入Properties类型
4.5.1、定义Bean
public class Cat {
private Properties props;
public void setProps(Properties props) {
this.props = props;
}
}
4.5.2、主配置文件配置Bean
<bean id="cat" class="cn.bdqn.Cat">
<property name="props">
<props>
<prop key="A001">虚竹</prop>
<prop key="A002">扫地僧</prop>
</props>
</property>
</bean>
4.6、总结
-
用于给List结构集合注入的标签:
list、array、set
-
用于个Map结构集合注入的标签:
map 、props
-
总结
结构相同,标签可以互换
好书推荐
《Spring Batch权威指南》主要内容:
-
探索Spring Batch 4中的新特性。
-
使用Spring Batch项目在云环境中完成有限的批处理任务。
-
通过一些示例,理解z新的基于Java和Spring Boot的配置技术
-
掌握复杂场景和云环境中的批处理
-
开发能够运行在现代平台上的批处理应用
-
除了Spring Batch,使用Spring Portfolio的其他部分开发关键任务型批处理应用
购书链接:点此进入
送书活动
参与方式:点击进入参与 公平公正公开 人少好中奖!