依赖注入( Dependency Injection ,简称 DI) 与控制反转 (IoC) 的含义相同,只不过这两个称呼是从两个角度描述的同一个概念。
- 依赖:bean对象的创建依赖于容器。
- 注入:bena对象中的所有属性,由容器来注入。
- 控制反转(IoC:依赖注入的另一种说法是“控制反转”,通俗的理解是:平常我们new一个实例,这个实例的控制权是我们程序员,而控制反转是指new实例工作不由我们程序员来做而是交给spring容器来做。
需要相关的jar包:
<dependencies>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.3.5</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
</dependencies>
1. 构造器注入
Dao层
public interface UserDao {
public void save();
}
public class UserDaoImpl implements UserDao {
public void save(){
System.out.println("save running...");
}
}
Service层
public interface UserService {
public void save();
}
public class UserServiceImpl implements UserService {
private UserDao userDao;
// 构造器注入
public UserServiceImpl(UserDao userDao) {
this.userDao = userDao;
}
// setter方法注入
/*public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}*/
public void save() {
userDao.save();
System.out.println("save runned...");
}
}
applicationContext.xml配置文件
<!-- 构造器注入 -->
<bean id="userDao" class="dao.impl.UserDaoImpl"></bean>
<bean id="userService" class="service.impl.UserServiceImpl">
<constructor-arg index="0" ref="userDao"></constructor-arg>
</bean>
测试类
/**
* 依赖注入测试
*/
@Test
public void TestIoC (){
ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");
UserService userService = (UserService) app.getBean("userService");
userService.save();
}
运行结果:
save running...
save runned...
注:解决构造方法参数的不确定性,你可能会遇到构造方法传入的两参数都是同类型的,为了分清哪个该赋对应值,xml配置文件则需要进行一些小处理,如:
<bean id="userDao" class="dao.impl.UserDaoImpl"></bean>
<bean id="springDao" class="dao.impl.SpringDaoImpl"></bean>
<!-- 构造器注入 -->
<bean id="userService" class="service.impl.UserServiceImpl">
<constructor-arg index="0" ref="userDao"></constructor-arg>
<constructor-arg index="1" ref="springDao"></constructor-arg>
</bean>
<!-- 另一种是设置参数类型 -->
<bean id="userDao" class="dao.impl.UserDaoImpl"></bean>
<bean id="springDao" class="dao.impl.SpringDaoImpl"></bean>
<!-- 构造器注入 -->
<bean id="userService" class="service.impl.UserServiceImpl">
<constructor-arg type="java.lang.Integer" ref="userDao"></constructor-arg>
<constructor-arg type="java.lang.String" ref="springDao"></constructor-arg>
</bean>
<!-- 另一种是设置参数名字 -->
<bean id="userDao" class="dao.impl.UserDaoImpl"></bean>
<bean id="springDao" class="dao.impl.SpringDaoImpl"></bean>
<!-- 构造器注入 -->
<bean id="userService" class="service.impl.UserServiceImpl">
<constructor-arg name="userDao" ref="userDao"></constructor-arg>
<constructor-arg name="springDao" ref="springDao"></constructor-arg>
</bean>
2. 属性setter方式注入(比较常用)
Dao层
public interface UserDao {
public void save();
}
public class UserDaoImpl implements UserDao {
public void save(){
System.out.println("save running...");
}
}
Service层
public interface UserService {
public void save();
}
public class UserServiceImpl implements UserService {
private UserDao userDao;
// 构造器注入
/*public UserServiceImpl(UserDao userDao) {
this.userDao = userDao;
}*/
// setter方法注入
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
public void save() {
userDao.save();
System.out.println("save runned...");
}
}
applicationContext.xml配置文件
<!-- 构造器注入 -->
<!--<bean id="userDao" class="dao.impl.UserDaoImpl"></bean>
<bean id="userService" class="service.impl.UserServiceImpl">
<constructor-arg index="0" ref="userDao"></constructor-arg>
</bean>-->
<!-- setter方法注入 -->
<bean id="userDao" class="dao.impl.UserDaoImpl"></bean>
<bean id="userService" class="service.impl.UserServiceImpl">
<property name="userDao" ref="userDao"></property>
</bean>
测试类
/**
* 依赖注入测试
*/
@Test
public void TestIoC (){
ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");
UserService userService = (UserService) app.getBean("userService");
userService.save();
}
运行结果:
save running...
save runned...
3. p命名空间
在setter方法注入的基础上进行修改
在applicationContext.xml配置文件中添加第三方约束:xmlns:p="http://www.springframework.org/schema/p"
<?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
xmlns:p="http://www.springframework.org/schema/p" http://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- 构造器注入 -->
<!--<bean id="userDao" class="dao.impl.UserDaoImpl"></bean>
<bean id="userService" class="service.impl.UserServiceImpl">
<constructor-arg index="0" ref="userDao"></constructor-arg>
</bean>-->
<!-- setter方法注入 -->
<!--<bean id="userDao" class="dao.impl.UserDaoImpl"></bean>
<bean id="userService" class="service.impl.UserServiceImpl">
<property name="userDao" ref="userDao"></property>
</bean>-->
<!-- p命名空间,通过setter方法注入 -->
<bean id="userDao" class="dao.impl.UserDaoImpl"></bean>
<bean id="userService" class="service.impl.UserServiceImpl"
p:userDao-ref="userDao">
</bean>
</Beans>
4. c命名空间
同理,在使用前导入第三方约束xmlns:c="http://www.springframework.org/schema/c"
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:c="http://www.springframework.org/schema/c"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- 构造器注入 -->
<!--<bean id="userDao" class="dao.impl.UserDaoImpl"></bean>
<bean id="userService" class="service.impl.UserServiceImpl">
<constructor-arg index="0" ref="userDao"></constructor-arg>
</bean>-->
<!-- setter方法注入 -->
<!--<bean id="userDao" class="dao.impl.UserDaoImpl"></bean>
<bean id="userService" class="service.impl.UserServiceImpl">
<property name="userDao" ref="userDao"></property>
</bean>-->
<!-- p命名空间,通过setter方法注入 -->
<!--<bean id="userDao" class="dao.impl.UserDaoImpl"></bean>
<bean id="userService" class="service.impl.UserServiceImpl"
p:userDao-ref="userDao">
</bean>-->
<!-- c命名空间,通过构造器注入,即在实体类中需有有参构造和无参构造 -->
<bean id="userDao" class="dao.impl.UserDaoImpl"></bean>
<bean id="userService" class="service.impl.UserServiceImpl"
c:userDao-ref="userDao">
</bean>
</Beans>