这里写目录标题
- 1. setter注入
- 在一个类中注入引用类型
- 在一个类中注入简单类型
- 2. 构造器注入
- 在一个类中注入引用类型
- 在一个类中注入简单类型
- 3. 依赖注入方式选择
- 4. 依赖自动装配
- 按类型注入
- 按名称注入
- 5. 集合注入
1. setter注入
在一个类中注入引用类型
回顾一下之前setter注入的方法,我们有以下类:
BookDao.java
package com.example.demo.dao;public interface BookDao {void save();
}
BookDaoImpl.java
package com.example.demo.dao.impl;import com.example.demo.dao.BookDao;public class BookDaoImpl implements BookDao {@Overridepublic void save() {System.out.println("book dao save...");}
}
BookService.java
package com.example.demo.service;public interface BookService {void save();
}
BookServiceImpl.java
package com.example.demo.service.impl;import com.example.demo.dao.BookDao;
import com.example.demo.service.BookService;public class BookServiceImpl implements BookService {private BookDao bookDao;@Overridepublic void save() {System.out.println("book service save...");}
}
我们想要将BookDaoImpl
注入到BookServiceImpl
中,最简单的方法就是通过setter注入
第一步: 在BookServiceImpl
中建立bookDao
的setter
方法:
package com.example.demo.service.impl;import com.example.demo.dao.BookDao;
import com.example.demo.service.BookService;public class BookServiceImpl implements BookService {private BookDao bookDao;@Overridepublic void save() {System.out.println("book service save...");}public void setBookDao(BookDao bookDao) {this.bookDao = bookDao;}
}
第二步: 配置bookDao,和bookService两个bean(在resource下建立Spring Config文件):
<?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="bookDao" class="com.example.demo.dao.impl.BookDaoImpl"/><bean id="bookService" class="com.example.demo.service.impl.BookServiceImpl"><property name="bookDao" ref="bookDao" /></bean>
</beans>
id
属性为bean的名称,class
为对应需要注入的类
property
表示类里面需要注入的属性,name
是属性名称,ref
是属性的引用类,这里引用的是上面的bookDao
类
以上两步即可完成配置,测试一下:
package com.example.demo.service.impl;import com.example.demo.dao.BookDao;
import com.example.demo.service.BookService;public class BookServiceImpl implements BookService {private BookDao bookDao;@Overridepublic void save() {System.out.println("book service save...");bookDao.save();}public void setBookDao(BookDao bookDao) {this.bookDao = bookDao;}
}
结果是:
book service save...
book dao save...
在一个类中注入简单类型
假如在上面的BookDaoImpl.java
中,还有两个简单类型:
package com.example.demo.dao.impl;import com.example.demo.dao.BookDao;public class BookDaoImpl implements BookDao {private int connectNum;private String databaseName;@Overridepublic void save() {System.out.println("book dao save...");System.out.println("connectNum:" + connectNum + ", databaseName:" + databaseName);}
}
第一步: 如果使用setter注入,首先给这两个简单类型写set方法:
public void setConnectNum(int connectNum) {this.connectNum = connectNum;
}public void setDatabaseName(String databaseName) {this.databaseName = databaseName;
}
第二步: 配置的时候,bookDao
的配置应该这样写:
<bean id="bookDao" class="com.example.demo.dao.impl.BookDaoImpl"><property name="connectNum" value="10"/><property name="databaseName" value="name" />
</bean>
name
表示属性的名字,value
表示赋予简单类型的值
再执行一下上面写的测试主方法(此处略),结果为:
book service save...
book dao save...
connectNum:10, databaseName:name
总结简单类型的注入:
2. 构造器注入
在一个类中注入引用类型
BookDao.java
package com.example.demo.dao;public interface BookDao {void save();
}
BookDaoImpl.java
package com.example.demo.dao.impl;import com.example.demo.dao.BookDao;public class BookDaoImpl implements BookDao {@Overridepublic void save() {System.out.println("book dao save...");}
}
BookService.java
package com.example.demo.service;public interface BookService {void save();
}
BookServiceImpl.java
package com.example.demo.service.impl;import com.example.demo.dao.BookDao;
import com.example.demo.service.BookService;public class BookServiceImpl implements BookService {private BookDao bookDao;@Overridepublic void save() {System.out.println("book service save...");}
}
我们想使用构造器注入在bookServiceImpl
中注入bookDao
,方法如下:
第一步: 在bookServiceImpl中写构造方法
public BookServiceImpl(BookDao bookDao) {this.bookDao = bookDao;}
第二步: 在配置中配置有参构造方法,通过constructor-arg
标签进行构造,也就是向bookDao类型中传入一个什么样的参数
<?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="bookDao" class="com.example.demo.dao.impl.BookDaoImpl"/><bean id="bookService" class="com.example.demo.service.impl.BookServiceImpl"><constructor-arg name="bookDao" ref="bookDao"/></bean>
</beans>
再运行主方法,可以获得一样的结果:
book service save...
book dao save...
同样的,假如我们还有一个UserDaoImpl
:
UserDao.java:
package com.example.demo.dao;public interface UserDao {void save();
}
UserDaoImpl.java:
package com.example.demo.dao.impl;import com.example.demo.dao.UserDao;public class UserDaoImpl implements UserDao {@Overridepublic void save() {System.out.println("user dao save...");}
}
我们在BookServiceImpl
中还引入了这个类型:
package com.example.demo.service.impl;import com.example.demo.dao.BookDao;
import com.example.demo.dao.UserDao;
import com.example.demo.service.BookService;public class BookServiceImpl implements BookService {private BookDao bookDao;private UserDao userDao;public BookServiceImpl(BookDao bookDao) {this.bookDao = bookDao;}@Overridepublic void save() {System.out.println("book service save...");bookDao.save();userDao.save();}
}
则需要重新写一下构造方法:
public BookServiceImpl(BookDao bookDao, UserDao userDao) {this.bookDao = bookDao;this.userDao = userDao;}
并多加一行对userDao的配置:
<?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="bookDao" class="com.example.demo.dao.impl.BookDaoImpl"/><bean id="userDao" class="com.example.demo.dao.impl.UserDaoImpl"/><bean id="bookService" class="com.example.demo.service.impl.BookServiceImpl"><constructor-arg name="bookDao" ref="bookDao"/><constructor-arg name="userDao" ref="userDao"/></bean>
</beans>
再次运行测试函数,结果如下:
book service save...
book dao save...
user dao save...
在一个类中注入简单类型
BookDao
代码如下:
package com.example.demo.dao.impl;import com.example.demo.dao.BookDao;public class BookDaoImpl implements BookDao {private int connectNum;private String databaseName;@Overridepublic void save() {System.out.println("book dao save...");}
}
想要给两个简单类型属性做配置,方法都是一样的:
第一步: 创建构造方法
package com.example.demo.dao.impl;import com.example.demo.dao.BookDao;public class BookDaoImpl implements BookDao {private int connectNum;private String databaseName;public BookDaoImpl(int connectNum, String databaseName) {this.connectNum = connectNum;this.databaseName = databaseName;}@Overridepublic void save() {System.out.println("book dao save...");System.out.println("connectNum:" + connectNum + ", databaseName:" + databaseName);}
}
第二步: 配置属性
<?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="bookDao" class="com.example.demo.dao.impl.BookDaoImpl"><constructor-arg name="connectNum" value="10"/><constructor-arg name="databaseName" value="aaa"/></bean><bean id="userDao" class="com.example.demo.dao.impl.UserDaoImpl"/><bean id="bookService" class="com.example.demo.service.impl.BookServiceImpl"><constructor-arg name="bookDao" ref="bookDao"/><constructor-arg name="userDao" ref="userDao"/></bean>
</beans>
运行后结果为:
book service save...
book dao save...
connectNum:10, databaseName:aaa
user dao save...
除了通过name指定配置的参数,还有两种办法指定:
我们上面通过name指定的是标准写法
第一种是通过参数类型进行指定(是为了解耦,避免配置和name耦合)
第二种是通过参数位置进行指定(为了解决有同样类型的参数的问题)
3. 依赖注入方式选择
建议使用setter注入
第三方技术根据情况选择
4. 依赖自动装配
定义:
注意,想要让IoC容器实现自动装配,必须给这些属性配置setter方法!
按类型注入
这些属性的类型要能够在配置的bean中的类型对应的上:
假如配置了两个指向同一类型,id不同的bean,显而易见bookService那里已经报红了:
如果仍让执行报错会提示,找到了两个bean,不知道匹配哪一个:
所以bean的类型指向必须唯一!
按名称注入
这些属性的名称要能够在配置的bean中的id对应的上:
5. 集合注入
假设我们的BookDaoImpl.java
中有以下的数据类型
package com.example.demo.dao.impl;import com.example.demo.dao.BookDao;import java.util.*;public class BookDaoImpl implements BookDao {private int[] array;private List<String> list;private Set<String> set;private Map<String, String> map;private Properties properties;@Overridepublic void save() {System.out.println("book dao save...");System.out.println("遍历数组:" + Arrays.toString(array));System.out.println("遍历List:" + list);System.out.println("遍历set:" + set);System.out.println("遍历Map:" + map);System.out.println("遍历properties:" + properties);}public void setProperties(Properties properties) {this.properties = properties;}public void setMap(Map<String, String> map) {this.map = map;}public void setSet(Set<String> set) {this.set = set;}public void setList(List<String> list) {this.list = list;}public void setArray(int[] array) {this.array = array;}
}
配置文件如下写:
<bean id="bookDao" class="com.example.demo.dao.impl.BookDaoImpl"><property name="array"><array><value>100</value><value>200</value><value>300</value></array></property><property name="list"><list><value>a</value><value>b</value><value>c</value></list></property><property name="set"><set><value>c</value><value>c</value><value>d</value></set></property><property name="map"><map><entry key="country" value="china" /><entry key="province" value="guangdong" /><entry key="city" value="shenzhen" /></map></property><property name="properties"><props><prop key="country">china</prop><prop key="province">henan</prop><prop key="city">kaifeng</prop></props></property></bean>
set是会自动过滤重复元素的,结果如下:
book service save...
book dao save...
遍历数组:[100, 200, 300]
遍历List:[a, b, c]
遍历set:[c, d]
遍历Map:{country=china, province=guangdong, city=shenzhen}
遍历properties:{country=china, province=henan, city=kaifeng}
如果数组里面是引用类型,写法就是:
<property name="array"><array><ref bean="beanId" /></array>
</property>