IOC控制反转是什么?
传统开发:开发者主动 new 创建对象、管理依赖;
控制反转:把对象的创建、生命周期管理、依赖装配交给 Spring 容器,控制权从代码转移到容器,所以叫反转。
IoC 容器里到底装了什么?(Bean 与 BeanFactory)
Spring 的 IoC 容器本质上是一个超级工厂,它里面装满了由 Spring 管理的 Java 对象,这些对象统称为 Bean。
容器的核心接口是:
-
BeanFactory:Spring 最底层的 IoC 容器,提供最基础的管理功能(延迟加载)。
-
ApplicationContext(应用上下文):它是 BeanFactory 的子接口,功能更强大(支持国际化、事件发布、AOP 集成等),我们在实际开发中用的就是它。
DI(Dependency Injection)依赖注入
在容器中建关系的整个过程是,称为依赖注入。
依赖注入它是实现 IoC 的一种主要方式。
例如:
@Servicepublic class UserService {
private final UserDao userDao;
public UserService(UserDao userDao) {
this.userDao = userDao;
}
}
Spring 创建 UserService 时发现:
UserService
↓
需要 UserDao
↓
IoC 容器查找 UserDao Bean
↓
创建/获取 UserDao
↓
注入 UserService
Spring 是怎么知道哪些对象需要管理的?
1. 注解扫描
例如:
@Component
public class UserDao {
}
@Service
public class UserService {
}
@Controller
public class UserController {
}
Spring 启动时进行组件扫描,发现这些类以后,把它们注册到 IoC 容器。
2. @Bean
也可以手动注册:Spring 会把返回的对象放入 IoC 容器。
@Configurationpublic class AppConfig {
@Bean
public UserService userService() {
return new UserService();
}
}
IoC 是怎么实现的?
Spring 主要通过 IoC 容器实现控制反转。项目启动时,Spring 会扫描 @Component、@Service、@Repository、@Controller 等组件,解析 Bean 定义并创建 Bean,保存到 IoC 容器中。当某个 Bean 依赖其他 Bean 时,Spring 根据依赖关系进行自动装配和注入,例如通过 @Autowired、@Resource 或构造器注入完成依赖关系建立。
Spring 启动
↓
加载配置
↓
组件扫描
↓
找到 @Component、@Service 等组件
↓
解析 Bean 定义
↓
创建 Bean
↓
处理 Bean 依赖
↓
依赖注入
↓
初始化 Bean
↓
放入 IoC 容器
↓
业务代码获取并使用 Bean
降低耦合解析
没有 IoC 时(高耦合):
public class UserService {
// 自己主动 new 实现类,写死了
private UserDao userDao = new MySqlUserDao();
public void doSomething() {
userDao.save();
}
}
如果要把 MySqlUserDao 换成 OracleUserDao,必须修改 UserService 的源码。
使用 Spring IoC 后(低耦合):
@Service
public class UserService {
@Autowired // 由容器把合适的实现注入进来
private UserDao userDao;
public void doSomething() {
userDao.save();
}
}
@Repository
public class OracleUserDao implements UserDao { ... }
现在,UserService 只依赖 UserDao 接口。至于容器注入的是 MySqlUserDao 还是 OracleUserDao,完全由配置决定,UserService 的源码无需改动。