在学习的第一天就跟着demo练习了一番spring依赖注入的
具体操作,在接下来的几天对于为什么要这么做有了一定的认识,今天对于依赖注入的具体方式来进行一下细分。
一、构造函数注入
通过构造函数来进行依赖关系的设定,默认是使用的无参构造,如果重写了构造函数改成带参数的而没有无参构造,直接使用如下注入会失败。
String name;
Integer price;
Date byDate;
public Car(String name, Integer price, Date byDate) {
this.name = name;
this.price = price;
this.byDate = byDate;
}
<bean name="car" class="com.pojo.Car" ></bean>
运行后错误提示
Exception in thread "main" org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'car' defined in class path resource [applicationContext.xml]: Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.pojo.Car]: No default constructor found; nested exception is java.lang.NoSuchMethodException: com.pojo.Car.<init>()
配置
这个时候如果要使用构造器注入对应的属性应该使用标签constructor-arg来注入有参构造的参数。
其中的属性如下:
type:通过指定要注入数据的数据类型,该数据类型也是构造函数中某个参数的类型(同参数类型的参数会引起混乱)
index:用于指定要注入数据给构造函数中指定索引位置的参数赋值,索引位置是从0开始。
name:用于指定给构造函数中指定名称的参数赋值(常用)
赋值类型:
value:基本类型和String类型赋值
ref:用于指定其他的bean类型数据(交给spring管理的bean对象)
代码示例
<bean name="car" class="com.pojo.Car" >
<constructor-arg name="name" value="雷克萨斯"></constructor-arg>
<constructor-arg name="price" value="600000"></constructor-arg>
<constructor-arg name="byDate" value="2018-1-1"></constructor-arg>
</bean>
此处Integer类型直接使用value可以将写入的值进行转换,但是Date类型并不会进行转换。
提示如下:
Could not convert argument value of type [java.lang.String] to required type [java.util.Date]: Failed to convert value of type 'java.lang.String' to required type 'java.util.Date'
正确的写法应该先配置一个日期对象然后使用ref引用改对象对其进行赋值。
<bean name="car" class="com.pojo.Car" >
<constructor-arg name="name" value="雷克萨斯"></constructor-arg>
<constructor-arg name="price" value="600000"></constructor-arg>
<constructor-arg name="byDate" ref="newDate"></constructor-arg>
</bean>
<bean name="newDate" class="java.util.Date"></bean>
总结:
优势:获取对象时,注入必须的操作否则对象没法创建成功。
弊端:改变了bean对象的实例化方式,如果创建对象用不到的数据,但是也必须提供。
方法注入(常用)
配置
标签:property
位置:bean标签内部
属性:
name:用于指定注入时所调用的set方法名称(注意是set方法名称,与变量名无关)
value:用于提供基本类型和String类型的数据
ref:用于指定其他的bean类型数据。(交给spring管理的bean对象)
代码示例
public class Car {
String name;
Integer price;
Date byDate;
public void setName(String name) {
this.name = name;
}
public void setPrice(Integer price) {
this.price = price;
}
public void setByDate(Date byDate) {
this.byDate = byDate;
}
}
调用set方法,使用默认无参构造函数。
<bean name="car" class="com.pojo.Car" >
<property name="name" value="梅赛德斯"/>
<property name="byDate" ref="newDate"/>
<property name="price" value="1000000"/>
</bean>
总结
优势:创建对象时没有明确限制,可以直接使用默认的构造函数
弊端:如果某个成员必须有值,获取对象时有可能set方法还没有执行。
复合类型注入
对于参数是集合类型的注入方法
配置
标签:还是使用的set注入的标签property
位置:bean标签内部
代码示例
public class Car {
String[] strs;
List list;
Map map;
Set set;
public void setList(List list) {
this.list = list;
}
public void setMap(Map map) {
this.map = map;
}
public void setStrs(String[] strs) {
this.strs = strs;
}
}
public void setSet(Set set) {
this.set = set;
}
<bean name="car" class="com.pojo.Car" >
<property name="list">
<list>
<value>111</value>
<value>222</value>
</list>
</property>
<property name="set">
<set>
<value>111</value>
<value>222</value>
</set>
</property>
<property name="strs">
<array>
<value>111</value>
<value>222</value>
</array>
</property>
<property name="map">
<map>
<entry key="no1" value="abc"></entry>
<entry key="no2" value="qwe"></entry>
<entry key="no3" value="zxc"></entry>
</map>
</property>
但是在使用时发现关于list 、set 、数组类型的时候因为数据结构类型的类似,标签使用同一个也是可以注入的。
例:
<bean name="car" class="com.pojo.Car" >
<property name="list">
<list>
<value>111</value>
<value>222</value>
</list>
</property>
<property name="set">
<list>
<value>111</value>
<value>222</value>
</list>
</property>
<property name="strs">
<list>
<value>111</value>
<value>222</value>
</list>
</property>
<property name="map">
<map>
<entry key="no1" value="abc"></entry>
<entry key="no2" value="qwe"></entry>
<entry key="no3" value="zxc"></entry>
</map>
</property>
总结:
关于集合类型的注入其实就分为两种一种是list(也可以使用set、array)、一种是map、props的键值类型,类型相同标签可以互换。