Week 1-8: Spring Boot 学习计划完整项目
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
164
week2/src/main/java/com/learn/ioc/SimpleIocDemo.java
Normal file
164
week2/src/main/java/com/learn/ioc/SimpleIocDemo.java
Normal file
@@ -0,0 +1,164 @@
|
||||
package com.learn.ioc;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 第 1 天:手写简易 IoC 容器 —— 理解控制反转的本质
|
||||
*
|
||||
* 核心概念:
|
||||
* IoC(Inversion of Control):把"创建对象"的控制权从程序员手里
|
||||
* 交给容器。以前是 new 一个对象,现在是容器帮我们创建并注入。
|
||||
*
|
||||
* DI(Dependency Injection):依赖注入,IoC 最常见的实现方式。
|
||||
* 当 A 类需要 B 类时,不需要 A 自己 new B,而是由容器把 B 注入到 A 中。
|
||||
*
|
||||
* 这个类是一个极简 IoC 容器实现,只依赖 JDK,用于理解 Spring 的核心思想。
|
||||
*
|
||||
* 运行方式:IDEA 中右键此类 → Run 'SimpleIocDemo.main()'
|
||||
*/
|
||||
public class SimpleIocDemo {
|
||||
|
||||
// ==================== 1. 定义两个简单的"业务类" ====================
|
||||
|
||||
/** 模拟一个"数据访问层"组件 */
|
||||
static class UserRepository {
|
||||
public String findUser() {
|
||||
return "张三(来自数据库)";
|
||||
}
|
||||
}
|
||||
|
||||
/** 模拟一个"业务逻辑层"组件 —— 它依赖 UserRepository */
|
||||
static class UserService {
|
||||
// UserService 需要 UserRepository,但自己不 new
|
||||
private UserRepository userRepository;
|
||||
|
||||
// 通过 setter 方法接收依赖(这就是"注入")
|
||||
public void setUserRepository(UserRepository userRepository) {
|
||||
this.userRepository = userRepository;
|
||||
}
|
||||
|
||||
public String getUserInfo() {
|
||||
return userRepository.findUser();
|
||||
}
|
||||
}
|
||||
|
||||
// ==================== 2. 极简 IoC 容器 ====================
|
||||
|
||||
/**
|
||||
* 一个玩具级 IoC 容器,实现两个能力:
|
||||
* 1. 注册 Bean(把对象放进容器)
|
||||
* 2. 注入依赖(帮对象建立关联关系)
|
||||
*/
|
||||
static class SimpleContainer {
|
||||
// 存储所有 Bean:名字 → 对象
|
||||
private final Map<String, Object> beans = new HashMap<>();
|
||||
|
||||
/** 注册一个 Bean */
|
||||
public void register(String name, Object bean) {
|
||||
beans.put(name, bean);
|
||||
}
|
||||
|
||||
/** 获取一个 Bean */
|
||||
public Object getBean(String name) {
|
||||
return beans.get(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* 自动注入:扫描每个 Bean 中带 @Autowired 注解的字段,自动赋值
|
||||
* (这里用我们自定义的注解来模拟 Spring 的 @Autowired)
|
||||
*/
|
||||
public void autowire() {
|
||||
for (Object bean : beans.values()) {
|
||||
for (Field field : bean.getClass().getDeclaredFields()) {
|
||||
if (field.isAnnotationPresent(MyAutowired.class)) {
|
||||
field.setAccessible(true);
|
||||
try {
|
||||
// 根据字段类型找到匹配的 Bean
|
||||
Object dependency = findBeanByType(field.getType());
|
||||
if (dependency != null) {
|
||||
field.set(bean, dependency);
|
||||
}
|
||||
} catch (IllegalAccessException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Object findBeanByType(Class<?> type) {
|
||||
for (Object bean : beans.values()) {
|
||||
if (type.isAssignableFrom(bean.getClass())) {
|
||||
return bean;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// ==================== 3. 自定义注解(模拟 Spring 的 @Autowired) ====================
|
||||
|
||||
@java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.RUNTIME)
|
||||
@interface MyAutowired {
|
||||
}
|
||||
|
||||
// ==================== 4. 使用注解版本测试自动注入 ====================
|
||||
|
||||
static class OrderRepository {
|
||||
public String getOrder() {
|
||||
return "订单 #12345";
|
||||
}
|
||||
}
|
||||
|
||||
static class OrderService {
|
||||
@MyAutowired // 告诉容器:帮我把 OrderRepository 注入进来
|
||||
private OrderRepository orderRepository;
|
||||
|
||||
public String getOrderInfo() {
|
||||
return orderRepository.getOrder();
|
||||
}
|
||||
}
|
||||
|
||||
// ==================== 5. 主方法——跑起来看效果 ====================
|
||||
|
||||
public static void main(String[] args) {
|
||||
System.out.println("========== IoC 容器原理演示 ==========\n");
|
||||
|
||||
// --- 方式一:手动注入(模拟 XML 配置时代的做法) ---
|
||||
System.out.println("--- 方式一:手动 setter 注入 ---");
|
||||
SimpleContainer container1 = new SimpleContainer();
|
||||
|
||||
UserRepository userRepo = new UserRepository();
|
||||
UserService userService = new UserService();
|
||||
|
||||
container1.register("userRepository", userRepo);
|
||||
container1.register("userService", userService);
|
||||
|
||||
// 手动注入依赖
|
||||
userService.setUserRepository(userRepo);
|
||||
|
||||
UserService service1 = (UserService) container1.getBean("userService");
|
||||
System.out.println("调用结果: " + service1.getUserInfo());
|
||||
|
||||
// --- 方式二:自动注入(模拟注解时代的做法) ---
|
||||
System.out.println("\n--- 方式二:注解自动注入 ---");
|
||||
SimpleContainer container2 = new SimpleContainer();
|
||||
|
||||
container2.register("orderRepository", new OrderRepository());
|
||||
container2.register("orderService", new OrderService());
|
||||
|
||||
// 一行代码,自动完成所有依赖注入
|
||||
container2.autowire();
|
||||
|
||||
OrderService service2 = (OrderService) container2.getBean("orderService");
|
||||
System.out.println("调用结果: " + service2.getOrderInfo());
|
||||
|
||||
// --- 对比总结 ---
|
||||
System.out.println("\n========== 总结 ==========");
|
||||
System.out.println("没有 IoC 容器时:A a = new A(); a.setB(new B()); // 自己控制一切");
|
||||
System.out.println("有了 IoC 容器后:@Autowired B b; // 容器自动注入,你只管用");
|
||||
System.out.println("\n这就是 Spring 的核心理念——控制反转!");
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user