依赖注入的方法
构造注入
核心原理:通过调用构造方法来给属性赋值
public class OrderService {
private OrderDao orderDao;
private UserDao userDao;
public OrderService(OrderDao orderDao, UserDao userDao) {
this.orderDao = orderDao;
this.userDao = userDao;
}
public void delete(){
}
}
<!--Spring配置文件-->
<bean id="orderDaoBean" class="com.powernode.spring6.dao.OrderDao"/>
<bean id="orderServiceBean" class="com.powernode.spring6.service.OrderService">
<!--第一个参数下标是0-->
<constructor-arg index="0" ref="orderDaoBean"/>
<!--第二个参数下标是1-->
<constructor-arg index="1" ref="userDaoBean"/>
</bean>
<bean id="userDaoBean" class="com.powernode.spring6.dao.UserDao"/>
或者不使用参数下标,使用参数名字:
<!--Spring配置文件-->
<bean id="orderDaoBean" class="com.powernode.spring6.dao.OrderDao"/>
<bean id="orderServiceBean" class="com.powernode.spring6.service.OrderService">
<!--这里使用了构造方法上参数的名字-->
<constructor-arg name="orderDao" ref="orderDaoBean"/>
<constructor-arg name="userDao" ref="userDaoBean"/>
</bean>
<bean id="userDaoBean" class="com.powernode.spring6.dao.UserDao"/>
通过构造方法注入的时候:
- 可以通过下标
- 可以通过参数名
- 也可以不指定下标和参数名,可以类型自动推断。
set注入
set注入
set注入,基于set方法实现的,底层会通过反射机制调用属性对应的set方法然后给属性赋值。这种方式要求属性必须对外提供set方法。
1、声明对应的Bean
2、为该Bean创造set方法
3、在Spring配置文件中,对应的Bean里,通过property 标签传入name和ref
4、name为set方法去掉“set”并且第一个字母小写,ref为传入set方法的bean的id
public class UserService {
private UserDao userDao;
// 使用set方式注入,必须提供set方法。
// 反射机制要调用这个方法给属性赋值的。
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
public void save(){
userDao.insert();
}
}
<!--Spring配置文件-->
<bean id="userDaoBean" class="com.powernode.spring6.dao.UserDao"/>
<bean id="userServiceBean" class="com.powernode.spring6.service.UserService">
<!--set方法名为:setUserDao,name为去掉set,后面字符串第一个字母小写,ref为要注入的bean的id-->
<property name="userDao" ref="userDaoBean"/>
</bean>
set注入外部Bean
上面的set注入方式就是注入的外部Bean,即bean定义到外面,在property标签中使用ref属性进行注入。
set注入内部Bean
内部Bean的方式:在bean标签中嵌套bean标签
<!--Spring配置文件-->
<bean id="userServiceBean" class="com.powernode.spring6.service.UserService">
<property name="userDao">
<bean class="com.powernode.spring6.dao.UserDao"/>
</property>
</bean>
set注入简单类型
set方法中不是类对象,是int等简单类型也可以注入
public class User {
private int age;
//set方法里面是简单类型int
public void setAge(int age) {
this.age = age;
}
}
<!--Spring配置文件-->
<bean id="userBean" class="com.powernode.spring6.beans.User">
<!--简单类型在注入的时候要使用value属性,不能使用ref-->
<property name="age">
<value>20</value>
</property>
</bean>
或者
<!--Spring配置文件-->
<bean id="userBean" class="com.powernode.spring6.beans.User">
<!--简单类型在注入的时候要使用value属性,不能使用ref-->
<property name="age" value="20"/>
</bean>
简单类型包括:
- 基本数据类型
- 基本数据类型对应的包装类
- String或其他的CharSequence子类
- Number子类
- Date子类
- Enum子类
- URI
- URL
- Temporal子类
- Locale
- Class
- **另外还包括以上简单值类型对应的数组类型
需要注意的是:
如果把Date当做简单类型的话,日期字符串格式不能随便写。格式必须符合Date的toString()方法格式。显然这就比较鸡肋了。如果我们提供一个这样的日期字符串:2010-10-11,在这里是无法赋值给Date类型的属性的。
spring6之后,当注入的是URL,那么这个url字符串是会进行有效性检测的。如果是一个存在的url,那就没问题。如果不存在则报错。
级联属性赋值
级联属性赋值就是给 注入的Bean 的属性赋值,看下图:
一般ClazzBean的属性应该在自己的bean标签下赋值,若是在StudentBean标签下赋值,就是级联属性赋值:
是需要注意:
1、
<!--Spring配置文件-->
<bean id="clazzBean" class="com.powernode.spring6.beans.Clazz"/>
<bean id="student" class="com.powernode.spring6.beans.Student">
<property name="name" value="张三"/>
<!--要点1:以下两行配置的顺序不能颠倒-->
<property name="clazz" ref="clazzBean"/>
<!--要点2:clazz属性必须有getter方法-->
<property name="clazz.name" value="高三一班"/>
</bean>
2、
public class Clazz {
private String name;
public Clazz() {
}
//使用级联属性赋值,级联赋值的属性,例如clazz.name必须有get方法
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
注入数组
1、当数组中的元素是简单类型:
public class Person {
private String[] favariteFoods;
public void setFavariteFoods(String[] favariteFoods) {
this.favariteFoods = favariteFoods;
}
}
标签使用property,属性name对应set方法。array标签包裹一组数据,数组每个元素的赋值用value标签:
<bean id="person" class="com.powernode.spring6.beans.Person">
<property name="favariteFoods">
<array>
<value>鸡排</value>
<value>汉堡</value>
<value>鹅肝</value>
</array>
</property>
</bean>
2、当数组中的元素是非简单类型:一个订单中包含多个商品:
public class Order {
//数组中的元素非简单类型
private Goods[] goods;
public void setGoods(Goods[] goods) {
this.goods = goods;
}
}
标签使用property,属性name对应set方法。array标签包裹一组数据,数组每个元素的赋值用ref标签,
ref标签内的bean属性为需要赋值的bean的id
1、先创造不同的非简单类型对象
<bean id="goods1" class="com.powernode.spring6.beans.Goods">
<property name="name" value="西瓜"/>
</bean>
<bean id="goods2" class="com.powernode.spring6.beans.Goods">
<property name="name" value="苹果"/>
</bean>
2、通过ref标签给数组的每个元素赋值
<bean id="order" class="com.powernode.spring6.beans.Order">
<property name="goods">
<array>
<!--这里使用ref标签即可-->
<ref bean="goods1"/>
<ref bean="goods2"/>
</array>
</property>
</bean>
注入List集合
List集合:有序可重复
public class People {
// 一个人有多个名字
private List<String> names;
public void setNames(List<String> names) {
this.names = names;
}
}
标签使用property,属性name对应set方法。list标签包裹一组数据,数组每个元素的赋值用value标签。
如果List集合中是简单类型使用value标签,反之使用ref标签:
<bean id="peopleBean" class="com.powernode.spring6.beans.People">
<property name="names">
<list>
<!--非简单类型可以使用ref,简单类型使用value-->
<value>铁锤</value>
<value>张三</value>
<value>张三</value>
<value>张三</value>
<value>狼</value>
</list>
</property>
</bean>
注入set集合
Set集合:无序不可重复
public class People {
// 一个人有多个电话
private Set<String> phones;
public void setPhones(Set<String> phones) {
this.phones = phones;
}
}
标签使用property,属性name对应set方法。set标签包裹一组数据,数组每个元素的赋值用value标签。
如果Set集合中是简单类型使用value标签,反之使用ref标签:
<bean id="peopleBean" class="com.powernode.spring6.beans.People">
<property name="phones">
<set>
<!--非简单类型可以使用ref,简单类型使用value-->
<value>110</value>
<value>110</value>
<value>120</value>
<value>120</value>
<value>119</value>
<value>119</value>
</set>
</property>
</bean>
注入Map集合
键值对
public class People {
// 一个人有多个住址
private Map<Integer, String> addrs;
public void setAddrs(Map<Integer, String> addrs) {
this.addrs = addrs;
}
}
标签使用property,属性name对应set方法。map标签包裹一组数据,数组每个元素的赋值用entry标签,属性key为Map的键,属性value为Map的值。
如果key不是简单类型,使用 key-ref 属性;如果value不是简单类型,使用 value-ref 属性:
<bean id="peopleBean" class="com.powernode.spring6.beans.People">
<property name="addrs">
<map>
<!--如果key不是简单类型,使用 key-ref 属性-->
<!--如果value不是简单类型,使用 value-ref 属性-->
<entry key="1" value="北京大兴区"/>
<entry key="2" value="上海浦东区"/>
<entry key="3" value="深圳宝安区"/>
</map>
</property>
</bean>
注入Properties
java.util.Properties继承java.util.Hashtable,所以Properties也是一个Map集合。
public class People {
private Properties properties;
public void setProperties(Properties properties) {
this.properties = properties;
}
}
标签使用property,属性name对应set方法。props标签包裹一组数据,数组每个元素的赋值用prop标签,属性key为Properties 的键,prop标签包裹的内容为Properties的值。
<bean id="peopleBean" class="com.powernode.spring6.beans.People">
<property name="properties">
<props>
<prop key="driver">com.mysql.cj.jdbc.Driver</prop>
<prop key="url">jdbc:mysql://localhost:3306/spring</prop>
<prop key="username">root</prop>
<prop key="password">123456</prop>
</props>
</property>
</bean>
注入null和空字符串
1、注入空字符串:使用<value/ > 或者 value=“”
public class Vip {
private String email;
public void setEmail(String email) {
this.email = email;
}
}
两种方式:
(1)标签使用property,属性name对应set方法。value=“”
(2)标签使用property,属性name对应set方法。嵌套一个 <value/ >
<bean id="vipBean" class="com.powernode.spring6.beans.Vip">
1、空串的第一种方式
<property name="email" value=""/>
2、空串的第二种方式
<property name="email">
<value/>
</property>
</bean>
2、注入null: 或者 不为该属性赋值
方式1、不为email属性赋值,即没有<property>标签
<bean id="vipBean" class="com.powernode.spring6.beans.Vip" />
方式2、在<property>标签内嵌套 <null/>
<bean id="vipBean" class="com.powernode.spring6.beans.Vip">
<property name="email">
<null/>
</property>
</bean>
注入的值中含特殊符号
XML中有5个特殊字符,分别是:< 和 > 和 ’ 和 "和 &
以上5个特殊符号在XML中会被特殊对待,会被当做XML语法的一部分进行解析,如果这些特殊符号直接出现在注入的字符串当中,会报错。
解决方案包括两种:
- 第一种:特殊符号使用转义字符代替。
- 第二种:将含有特殊符号的字符串放到:<![CDATA[]]> 当中。因为放在CDATA区中的数据不会被XML文件解析器解析。
注意:使用CDATA时,不能使用value属性,只能使用value标签。
<bean id="mathBean" class="com.powernode.spring6.beans.Math">
<property name="result">
<!--只能使用value标签-->
<value><![CDATA[2 < 3]]></value>
</property>
</bean>
P命名空间注入
目的:简化 set注入。
注意:
- 第一:在XML头部信息中添加p命名空间的配置信息:xmlns:p=“http://www.springframework.org/schema/p”
- 第二:p命名空间注入是基于setter方法的,所以需要对应的属性提供 setter方法。
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
1、加入p命名空间的配置信息
xmlns:p="http://www.springframework.org/schema/p"
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">
2、使用p命名空间方法,注入
<bean id="customerBean" class="com.powernode.spring6.beans.Customer" p:name="zhangsan" p:age="20"/>
</beans>
C命名空间注入
目的:简化 构造注入。
注意:
第一:需要在xml配置文件头部添加信息:xmlns:c=“http://www.springframework.org/schema/c”
第二:需要提供构造方法。
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
1、加入c命名空间的配置信息
xmlns:c="http://www.springframework.org/schema/c"
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">
2、使用c命名空间方法,注入。(带参数名称)
<bean id="myTimeBean" class="com.powernode.spring6.beans.MyTime" c:year="1970" c:month="1" c:day="1"/>
3、使用c命名空间方法,注入。(不带参数名称)
<bean id="myTimeBean" class="com.powernode.spring6.beans.MyTime" c:_0="2008" c:_1="8" c:_2="8"/>
</beans>
Util命名空间
目的:配置复用
注意:
1、在spring配置文件头部添加配置信息
2、提供set方法
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
1、util配置信息
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
1、util配置信息
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">
2、复用内容,id自定义,set方法为:setProperties()
<util:properties id="prop">
<prop key="driver">com.mysql.cj.jdbc.Driver</prop>
<prop key="url">jdbc:mysql://localhost:3306/spring</prop>
<prop key="username">root</prop>
<prop key="password">123456</prop>
</util:properties>
<bean id="dataSource1" class="com.powernode.spring6.beans.MyDataSource1">
3、ref为复用体的id,set方法为:setProperties()
<property name="properties" ref="prop"/>
</bean>
<bean id="dataSource2" class="com.powernode.spring6.beans.MyDataSource2">
<property name="properties" ref="prop"/>
</bean>
</beans>