1. Spring IoC 简介
1.1 什么是 Spring IoC?
IoC:Inversion of Control,中文译为“控制反转”。它不是什么技术,而是一种思想:将原先自己实例化的对象交给 IoC 容器去实现。
控制反转可以拆分成“控制”和“反转”两个词来理解
- 控制:指的是对象创建的权利
- 就是我们平常用的最多的 new 关键字
- 反转:指的是把控制权交给外部的容器
- 就是说我们不需要写 new 关键字来创建对象了,而是通过 IoC 容器来帮助我们实例化对象,以后我们用到哪个对象,就跟 IoC 容器要即可
1.2 使用 IoC 带来了哪些好处呢?
IoC 的思想就是两方之间不互相依赖,由第三方容器来管理相关资源。所以带来的好处有:
- 对象之间的耦合度或者说依赖程度降低
- 资源集中管理,实现资源的可配置和易管理
1.3 IoC 和 DI 的区别
IoC 是一种思想,将对象创建的权利交给 IoC 容器(Spring 框架)来管理。
DI:Dependency Injection,中文译为“依赖注入”,它是实现 IoC 最常见以及最合理的方式。
在 Spring 框架中,有三种注入方式(其实有四种,只不过接口注入的方式已经被废弃了)
- set 方法注入
public interface UserDao {
void insert();
}
public class UserDaoImpl implements UserDao {
@Override
public void insert() {
System.out.println("插入用户...");
}
}
public interface UserService {
void insert();
}
public class UserServiceImpl implements UserService {
UserDao userDao;
// set 方法注入
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
@Override
public void insert() {
userDao.insert();
}
}
public class Demo1 {
public static void main(String[] args) {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("classpath:beans.xml");
System.out.println("spring 容器启动成功");
UserService service = context.getBean("userService", UserService.class);
service.insert();
}
}
<?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="userDao" class="com.fyl.springboot.ioc.dao.UserDaoImpl"/>
<bean id="userService" class="com.fyl.springboot.ioc.service.UserServiceImpl">
<property name="userDao" ref="userDao"/>
</bean>
</beans>
- 构造器注入
以上面 set 注入的代码为基础,只需要修改 UserServiceImpl 和 beans.xml 即可
public class UserServiceImpl implements UserService {
UserDao userDao;
// 构造器注入
public UserServiceImpl(UserDaoImpl userDao) {
this.userDao = userDao;
}
@Override
public void insert() {
userDao.insert();
}
}
<?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="userDao" class="com.fyl.springboot.ioc.dao.UserDaoImpl"/>
<bean id="userService" class="com.fyl.springboot.ioc.service.UserServiceImpl">
<constructor-arg ref="userDao"/>
</bean>
</beans>
- 注解方式
@Autowired 默认按类型装配
@Qualifier 和 @Autowired 配合使用,可以指定 bean 的名称
@Resource 默认按名称装配,当找不到与名称匹配的 bean 时,才会按类型装配
注解的方式改动的代码有点多:
首先 beans.xml 里的内容跟前两个已经完全不一样了
其次 UserServiceImpl 和 UserDaoImpl 都需要加上 @Component 注解
@Component
public class UserDaoImpl implements UserDao {
@Override
public void insert() {
System.out.println("插入用户...");
}
}
@Component
public class UserServiceImpl implements UserService {
@Autowired
private UserDao userDao;
@Override
public void insert() {
userDao.insert();
}
}
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
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
http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
<!-- base-package 项目启动后,会扫描这个包下所有的 @Component 注解的类,注册到 Spring IoC 容器中 -->
<context:component-scan base-package="com.fyl.springboot.ioc"/>
<context:annotation-config/>
</beans>