控制反转,将对象的创建进行反转,常规情况下,对象都是开发者手动创建的,使用 loC 开发者不再需要创建对象,而是由IOC容器根据需求自动创建项目所需要的对象
- 不用IOC,所有对象IOC开发者自己创建
- 使用IOC,直接告诉框架,我需要哪些东西,然后spring框架创建,然后我们再拿出来用
IOC创建对象的方式:基于XML(少的很)和基于注解(配置类,扫描包)
基于XML:xml通过解析+反射创建对象。开发者把需要的对象在 XML 中进行配置,Spring 框架读取这个配置文件,根据配置文件的内容来创建对象。比较麻烦。
基于注解:
1,通过配置类:用一个java类来替代XML文件,把在XML中配置的内容放到配置类中
新建一个配置类,加@Configuration注解,这个类就相当于整个XML文件。这个类里面创建一个方法,就对应xml中的bean,返回对象即可。方法上加@Bean注解,让spring可以调用这个方法,将这个方法返回的对象存到IOC里面
怎么获取:Bean的名称默认是方法名,也可以通过@Bean改
感觉还是比较麻烦,写的东西太多了
2,扫包+注解
不再依赖XML和配置类,直接将bean的创建交给目标类,在目标类添加注解来创建
直接给类加注解,@Component注解告诉spring框架,这个类要被注入到IOC
怎么用:加载IOC容器,指定包名扫包,然后直接就可以取Bean
可以实现依赖注入
依赖注入,就是一个类里面有别的类,一个对象里有其他对象,那我在这个里面的对象上加个@Autowired自动注入注解:在IOC容器里找到对应Bean,再赋值给里面的类
@Autowired:默认通过类型注入,所以在类里面叫啥名都能取出。如果要通过名字去找,那就加@Qualifier注解:表示要找名字叫啥的bean
IOC容器本体在堆里面
Bean定义存储在方法区+堆里
BeanDefinition存储在堆内存
Bean实例存储在堆内存(单例池(
singletonObjects
))IOC容器实例、Bean实例在堆里
Bean类元数据在方法区
IOC容器本身是堆内存中的一个特殊对象
所有单例Bean实例存储在容器的
singletonObjects
(堆内存)类定义等元数据存储在方法区(Metaspace)
🌰 用“餐厅点餐”比喻 Spring IOC
想象你在一家餐厅吃饭,点了一份 红烧肉。
1. 传统方式(没有IOC)
- 你自己动手做菜(相当于传统Java开发):
- 你需要:买肉、切肉、炒菜、调味...(手动创建对象)
- 问题:耦合度高(如果你换了一道菜,整个流程都要改)
2. Spring IOC方式(控制反转)
- 你只需要点菜,厨师(Spring容器)帮你做:
- 你(程序员):告诉餐厅(Spring)你要什么(
@Component
、@Service
等) - 餐厅(Spring容器):
- 有一个菜单(Bean定义),记录所有能做的菜(
BeanDefinition
) - 有一个厨房(IOC容器),负责做菜(
ApplicationContext
) - 有一个服务员(依赖注入),把做好的菜端给你(
@Autowired
)
- 有一个菜单(Bean定义),记录所有能做的菜(
- 你(程序员):告诉餐厅(Spring)你要什么(
📌 关键名词解释
专业名词 | 餐厅比喻 | 作用 |
---|---|---|
IOC(控制反转) | 你不用自己做菜,交给餐厅 | 对象的创建权交给Spring |
DI(依赖注入) | 服务员把菜端给你 | 自动装配对象 |
Bean | 餐厅的菜(如红烧肉、鱼香肉丝) | Spring管理的Java对象 |
ApplicationContext | 餐厅的厨房+菜单系统 | Spring容器的核心接口 |
BeanDefinition | 菜单上的菜谱(记录怎么做) | 描述如何创建Bean |
@Component/@Service | 你在菜单上登记新菜 | 告诉Spring这个类要管理 |
@Autowired | 服务员自动送菜 | 自动注入依赖对象 |
🍳 代码示例
1. 传统方式(手动创建对象)
public class Restaurant {
public static void main(String[] args) {
// 你自己做菜(手动new对象)
Chef chef = new Chef();
Dish dish = chef.cook("红烧肉");
System.out.println("吃:" + dish.getName());
}
}
问题:如果换厨师(new AnotherChef()
),代码要改很多地方。
2. Spring IOC方式(自动管理对象)
(1) 定义Bean(登记菜单)
@Service // 告诉Spring:这是一个Bean,让容器管理
public class Chef {
public Dish cook(String name) {
return new Dish(name);
}
}
(2) 依赖注入(自动送菜)
@RestController
public class RestaurantController {
@Autowired // Spring自动找Chef对象并注入
private Chef chef;
@GetMapping("/order")
public String order() {
Dish dish = chef.cook("红烧肉");
return "吃:" + dish.getName();
}
}
优势:
- 不用自己
new Chef()
,Spring自动管理 - 换厨师(换实现类)不影响代码(只需改配置)
🔍 核心思想总结
- IOC(控制反转):对象的创建权交给Spring,你不用自己
new
。 - DI(依赖注入):Spring自动把依赖的对象(如
Chef
)注入到你的类里。 - Bean:Spring管理的对象(
@Component
、@Service
等标注的类)。 - ApplicationContext:Spring的“厨房”,负责创建和管理Bean。
🚀 一句话理解
传统开发:你自己做菜(手动new
对象)
Spring IOC:你点菜,餐厅(Spring)做好送给你(自动管理对象)
这样代码更灵活、更易维护! 🎯