关键词:Spring 源码, 依赖注入, DI, IoC 容器, 手写框架, 循环依赖, Java 反射
写在前面
在学习 Spring 框架的过程中,很多人都有这样一个困惑:每天都在使用 @Autowired、@Resource 进行依赖注入,但 Spring 到底是如何实现依赖注入的?构造注入和 Setter 注入有什么区别?循环依赖又是如何解决的?
本文将带你从零开始手写 Spring 的依赖注入功能,通过实际编码深入理解 Spring IoC 容器的核心原理。读完本文,你将能够:
- ✅ 理解依赖注入的本质和实现方式
- ✅ 手写实现构造器注入和属性注入
- ✅ 掌握循环依赖的检测与处理机制
- ✅ 深入理解 Spring Bean 的生命周期
目录
一、DI 依赖注入概述
1.1 什么是依赖注入
DI(Dependency Injection,依赖注入) 是 Spring 框架的核心概念之一。它指的是由容器在运行期动态地将某个依赖注入到对象之中。
简单来说:给 Bean 对象的成员变量赋值。
传统方式 vs 依赖注入:
// 传统方式:自己创建依赖
public class Girl {
private Boy boyfriend = new Boy(); // 自己创建
}
// 依赖注入:由容器注入
public class Girl {
private Boy boyfriend; // 容器注入
// 通过构造器注入
public Girl(Boy boyfriend) {
this.boyfriend = boyfriend;
}
}
1.2 依赖注入的本质
依赖注入的本质是 “赋值”,具体分为两种:
- 给构造方法参数赋值(构造器注入)
- 给属性赋值(属性注入/Setter 注入)
1.3 依赖注入的分类
依赖的来源
| 来源类型 | 说明 | 示例 |
|---|---|---|
| 构造参数依赖 | 通过构造方法传入 | public Girl(String name, Boy boy) |
| 属性依赖 | 通过字段注入 | private Boy boyfriend; |
值的类型
| 值类型 | 说明 | 示例 |
|---|---|---|
| 直接值 | 基本数据类型、String | "小丽", 20, 'C' |
| Bean 依赖 | 引用其他 Bean | new Boy() |
| 集合类型 | 数组、List、Set、Map | List<Boy>, Map<String, Object> |
复杂情况示例:
public class Girl {
public Girl(String name, int age, char cup, Boy boyfriend) {
// 直接值 + Bean 依赖混合
}
private List<Boy> boyFriends; // 集合中存储 Bean 依赖
private Map<String, Object> attributes; // Map 中存储混合类型
}
二、构造器注入实现
2.1 构造器注入分析
在非 IoC 场景下,我们创建对象时直接传入参数即可:
public static void main(String[] args) {
Boy boy = new Boy();
Girl girl = new Girl("小丽", 20, 'C', boy);
}
但在 IoC 容器中,我们需要通过反射来创建对象,这就要求我们能够获取到构造参数的依赖信息。
构造参数依赖的特点:
- 数量:参数个数不确定
- 顺序:参数顺序必须匹配
- 类型:可能是直接值或 Bean 引用
2.2 BeanReference 设计
为了区分直接值和Bean 依赖,我们设计 BeanReference 类:
/**
* Bean 引用
* 用于表示一个属性或参数依赖另一个 Bean
*/
public class BeanReference {
private String beanName; // 按名称依赖
private Class<?> beanType; // 按类型依赖
public BeanReference(String beanName) {
this.beanName = beanName;
}
public BeanReference(Class<?> beanType) {
this.beanType = beanType;
}
// getters...
}
使用示例:
// 区分直接值和 Bean 依赖
List<Object> args = new ArrayList<>();
args.add("小丽"); // 直接值:String
args.add(20); // 直接值:int
args.add('C'); // 直接值:char
args.add(new BeanReference("boy")); // Bean 依赖
判断逻辑:
if (obj instanceof BeanReference) {
// 是 Bean 依赖,需要从容器中获取
BeanReference ref = (BeanReference) obj;
realValue = getBean(ref.getBeanName());
} else {
// 是直接值,直接使用
realValue = obj;
}
复杂情况处理:
// 集合中包含 Bean 依赖
List<Object> boyFriends = new ArrayList<>();
boyFriends.add(new BeanReference("boy1"));
boyFriends.add(new BeanReference("boy2"));
// 需要遍历集合,将 BeanReference 替换为实际 Bean
for (int i = 0; i < boyFriends.size(); i++) {
if (boyFriends.get(i) instanceof BeanReference) {
boyFriends.set(i, getBean(((BeanReference) boyFriends.get(i)).getBeanName()));
}
}
2.3 构造器注入核心实现
BeanDefinition 扩展
public interface BeanDefinition {
// ... 其他方法
/**
* 获取构造参数值
*/
List<?> getConstructorArgumentValues();
/**
* 设置构造参数值
*/
void setConstructorArgumentValues(List<?> constructorArgumentValues);
}
默认实现
public class GenericBeanDefinition implements BeanDefinition {
private Class<?> beanClass;
private List<?> constructorArgumentValues; // 构造参数值
private String factoryBeanName;
private String factoryMethodName;
// 缓存构造方法或工厂方法(避免重复推断)
private Constructor<?> constructor;
private Method factoryMethod;
@Override
public List<?> getConstructorArgumentValues() {
return constructorArgumentValues;
}
@Override
public void setConstructorArgumentValues(List<?> constructorArgumentValues) {
this.constructorArgumentValues = constructorArgumentValues;
}
// ... getters/setters
}
BeanFactory 实现
public class DefaultBeanFactory implements BeanFactory {
private Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>();
private Map<String, Object> singletonObjects = new ConcurrentHashMap<>();
private ThreadLocal<Set<String>> buildingBeans = new ThreadLocal<>(); // 记录正在创建的 Bean
@Override
public Object getBean(String beanName) throws Exception {
return doGetBean(beanName);
}
private Object doGetBean(String beanName) throws Exception {
// 1. 从单例缓存中获取
Object bean = singletonObjects.get(beanName);
if (bean != null) {
return bean;
}
// 2. 检查循环依赖
if (isBuilding(beanName)) {
throw new Exception("检测到循环依赖: " + beanName);
}
// 3. 标记开始创建
markBuilding(beanName);
try {
// 4. 获取 BeanDefinition
BeanDefinition bd = beanDefinitionMap.get(beanName);
if (bd == null) {
throw new Exception("Bean not found: " + beanName);
}
// 5. 创建实例
Object instance = createBeanInstance(bd);
// 6. 属性注入
setPropertyDIValues(bd, instance);
// 7. 初始化
doInit(bd, instance);
// 8. 缓存单例
if (bd.isSingleton()) {
singletonObjects.put(beanName, instance);
}
return instance;
} finally {
// 9. 移除创建标记
unmarkBuilding(beanName);
}
}
/**
* 创建 Bean 实例
*/
private Object createBeanInstance(BeanDefinition bd) throws Exception {
// 有构造参数,通过构造器创建
if (bd.getConstructorArgumentValues() != null && !bd.getConstructorArgumentValues().isEmpty()) {
return createInstanceByConstructor(bd);
}
// 无参构造
return bd.getBeanClass().newInstance();
}
/**
* 通过构造器创建实例
*/
private Object createInstanceByConstructor(BeanDefinition bd) throws Exception {
// 1. 获取构造参数的真实值(解析 BeanReference)
Object[] args = getConstructorArgumentValues(bd);
// 2. 获取匹配的构造方法
Constructor<?> constructor = determineConstructor(bd, args);
// 3. 缓存构造方法
bd.setConstructor(constructor);
// 4. 通过反射创建实例
return constructor.newInstance(args);
}
/**
* 解析构造参数值
* 将 BeanReference 替换为实际的 Bean
*/
private Object[] getConstructorArgumentValues(BeanDefinition bd) throws Exception {
List<?> args = bd.getConstructorArgumentValues();
if (args == null || args.isEmpty()) {
return null;
}
Object[] realArgs = new Object[args.size()];
for (int i = 0; i < args.size(); i++) {
realArgs[i] = getRealValue(args.get(i));
}
return realArgs;
}
/**
* 获取真实值
*/
private Object getRealValue(Object value) throws Exception {
if (value instanceof BeanReference) {
// Bean 依赖,递归获取
BeanReference ref = (BeanReference) value;
if (ref.getBeanName() != null) {
return getBean(ref.getBeanName());
}
// 按类型获取...
}
return value;
}
/**
* 推断构造方法
*/
private Constructor<?> determineConstructor(BeanDefinition bd, Object[] args) throws Exception {
// 1. 如果已经缓存,直接返回
if (bd.getConstructor() != null) {
return bd.getConstructor();
}
// 无参数,返回无参构造
if (args == null || args.length == 0) {
return bd.getBeanClass().getConstructor();
}
// 2. 根据参数类型精确匹配
Class<?>[] paramTypes = new Class[args.length];
for (int i = 0; i < args.length; i++) {
paramTypes[i] = args[i].getClass();
}
Constructor<?> constructor = null;
try {
constructor = bd.getBeanClass().getConstructor(paramTypes);
} catch (NoSuchMethodException e) {
// 精确匹配失败,继续模糊匹配
}
// 3. 模糊匹配:遍历所有构造方法
if (constructor == null) {
outer:
for (Constructor<?> ct : bd.getBeanClass().getConstructors()) {
Class<?>[] parameterTypes = ct.getParameterTypes();
if (parameterTypes.length == args.length) {
for (int i = 0; i < parameterTypes.length; i++) {
// 检查类型是否兼容(考虑继承关系)
if (!parameterTypes[i].isAssignableFrom(args[i].getClass())) {
continue outer;
}
}
constructor = ct;
break;
}
}
}
if (constructor == null) {
throw new Exception("找不到匹配的构造方法: " + bd.getBeanClass());
}
return constructor;
}
// ========== 循环依赖检测 ==========
private boolean isBuilding(String beanName) {
Set<String> buildingSet = buildingBeans.get();
return buildingSet != null && buildingSet.contains(beanName);
}
private void markBuilding(String beanName) {
Set<String> buildingSet = buildingBeans.get();
if (buildingSet == null) {
buildingSet = new HashSet<>();
buildingBeans.set(buildingSet);
}
buildingSet.add(beanName);
}
private void unmarkBuilding(String beanName) {
Set<String> buildingSet = buildingBeans.get();
if (buildingSet != null) {
buildingSet.remove(beanName);
}
}
}
使用示例
// 1. 创建容器
DefaultBeanFactory factory = new DefaultBeanFactory();
// 2. 注册 CBean
GenericBeanDefinition cBeanDef = new GenericBeanDefinition();
cBeanDef.setBeanClass(CBean.class);
factory.registerBeanDefinition("cbean", cBeanDef);
// 3. 注册 ABean,带有构造参数依赖
GenericBeanDefinition aBeanDef = new GenericBeanDefinition();
aBeanDef.setBeanClass(ABean.class);
// 设置构造参数
List<Object> args = new ArrayList<>();
args.add("abean01"); // 直接值
args.add(new BeanReference("cbean")); // Bean 依赖
aBeanDef.setConstructorArgumentValues(args);
factory.registerBeanDefinition("abean", aBeanDef);
// 4. 获取 Bean
ABean aBean = (ABean) factory.getBean("abean");
aBean.doSomething();
2.4 循环依赖问题
什么是循环依赖
public class A {
public A(B b) {} // A 依赖 B
}
public class B {
public B(A a) {} // B 依赖 A
}
这种情况下,创建 A 需要 B,创建 B 又需要 A,形成死循环。
循环依赖的三种情况
┌─────┐ ┌─────┐
│ A │ ───> │ B │
└─────┘ └─────┘
▲ │
└────────────┘
情况1:构造器循环依赖(无法解决)
┌─────┐ ┌─────┐
│ A │ ───> │ B │
└─────┘ └─────┘
│
▼
┌─────┐
│ C │
└─────┘
│
▼
┌─────┐
│ A │
└─────┘
情况2:多例循环依赖(无法解决)
┌─────┐ ┌─────┐
│ A │ ───> │ B │
└─────┘ └─────┘
▲ │
└────────────┘
情况3:属性循环依赖(可以解决)
构造器循环依赖的检测
// 使用 ThreadLocal 记录正在创建的 Bean
private ThreadLocal<Set<String>> buildingBeans = new ThreadLocal<>();
private Object doGetBean(String beanName) throws Exception {
// 检查循环依赖
if (isBuilding(beanName)) {
throw new Exception("检测到循环依赖: " + beanName);
}
// 标记开始创建
markBuilding(beanName);
try {
// 创建 Bean...
} finally {
// 移除标记
unmarkBuilding(beanName);
}
}
构造器循环依赖无法解决,因为构造器注入要求在实例化时就提供所有依赖,而依赖又需要被依赖对象先创建完成。
三、属性注入实现
3.1 属性注入分析
属性注入是通过 setter 方法或直接反射给字段赋值。
public class Girl {
private String name;
private int age;
private char cup;
private List<Boy> boyFriends;
// setter 方法...
}
3.2 PropertyValue 设计
/**
* 属性值
* 记录属性名和对应的值
*/
public class PropertyValue {
private String name; // 属性名
private Object value; // 属性值(可能是直接值或 BeanReference)
public PropertyValue(String name, Object value) {
this.name = name;
this.value = value;
}
// getters...
}
3.3 属性注入核心实现
BeanDefinition 扩展
public interface BeanDefinition {
// ... 其他方法
/**
* 获取属性值列表
*/
List<PropertyValue> getPropertyValues();
/**
* 设置属性值
*/
void setPropertyValues(List<PropertyValue> propertyValues);
}
BeanFactory 实现
public class DefaultBeanFactory implements BeanFactory {
// 提前暴露正在创建的 Bean(用于解决循环依赖)
private ThreadLocal<Map<String, Object>> earlyExposeBeans = new ThreadLocal<>();
private Object doGetBean(String beanName) throws Exception {
// 1. 从单例缓存获取
Object bean = singletonObjects.get(beanName);
if (bean != null) {
return bean;
}
// 2. 从提前暴露缓存获取(解决循环依赖)
bean = getEarlyExposeBean(beanName);
if (bean != null) {
return bean;
}
// 3. 检查循环依赖
if (isBuilding(beanName)) {
throw new Exception("检测到循环依赖: " + beanName);
}
markBuilding(beanName);
try {
BeanDefinition bd = beanDefinitionMap.get(beanName);
// 4. 创建实例(此时还未注入属性)
Object instance = createBeanInstance(bd);
// 5. 提前暴露实例(解决属性循环依赖)
if (bd.isSingleton()) {
doEarlyExpose(beanName, instance);
}
// 6. 属性注入
setPropertyDIValues(bd, instance);
// 7. 初始化
doInit(bd, instance);
// 8. 缓存到单例池
if (bd.isSingleton()) {
singletonObjects.put(beanName, instance);
removeEarlyExpose(beanName);
}
return instance;
} finally {
unmarkBuilding(beanName);
}
}
/**
* 属性注入
*/
private void setPropertyDIValues(BeanDefinition bd, Object instance) throws Exception {
List<PropertyValue> propertyValues = bd.getPropertyValues();
if (propertyValues == null || propertyValues.isEmpty()) {
return;
}
for (PropertyValue pv : propertyValues) {
if (StringUtils.isBlank(pv.getName())) {
continue;
}
// 通过反射获取字段
Field field = instance.getClass().getDeclaredField(pv.getName());
field.setAccessible(true); // 暴力访问 private 字段
// 获取真实值(解析 BeanReference)
Object realValue = getRealValue(pv.getValue());
// 设置值
field.set(instance, realValue);
}
}
/**
* 提前暴露 Bean
*/
private void doEarlyExpose(String beanName, Object instance) {
Map<String, Object> earlyMap = earlyExposeBeans.get();
if (earlyMap == null) {
earlyMap = new HashMap<>();
earlyExposeBeans.set(earlyMap);
}
earlyMap.put(beanName, instance);
}
private Object getEarlyExposeBean(String beanName) {
Map<String, Object> earlyMap = earlyExposeBeans.get();
return earlyMap != null ? earlyMap.get(beanName) : null;
}
}
使用示例
// 1. 创建容器
DefaultBeanFactory factory = new DefaultBeanFactory();
// 2. 注册 Boy
GenericBeanDefinition boyDef = new GenericBeanDefinition();
boyDef.setBeanClass(Boy.class);
List<PropertyValue> boyProps = new ArrayList<>();
boyProps.add(new PropertyValue("name", "小明"));
boyDef.setPropertyValues(boyProps);
factory.registerBeanDefinition("boy", boyDef);
// 3. 注册 Girl,属性注入
GenericBeanDefinition girlDef = new GenericBeanDefinition();
girlDef.setBeanClass(Girl.class);
List<PropertyValue> girlProps = new ArrayList<>();
girlProps.add(new PropertyValue("name", "小丽"));
girlProps.add(new PropertyValue("age", 20));
girlProps.add(new PropertyValue("boyfriend", new BeanReference("boy")));
girlDef.setPropertyValues(girlProps);
factory.registerBeanDefinition("girl", girlDef);
// 4. 获取 Bean
Girl girl = (Girl) factory.getBean("girl");
System.out.println(girl.getName()); // 小丽
System.out.println(girl.getBoyfriend().getName()); // 小明
3.4 属性注入的循环依赖解决
为什么属性注入可以解决循环依赖?
// 非 IoC 场景下很容易解决
Boy b = new Boy();
Girl g = new Girl();
b.setGirl(g);
g.setBoy(b);
关键点:分步骤创建对象
- 先创建对象(此时属性为 null)
- 再注入属性
提前暴露机制
// 创建流程:
// 1. 实例化 A(调用构造器)
A a = new A();
// 2. 提前暴露 A(放入缓存)
earlyExposeBeans.put("a", a);
// 3. 注入 A 的属性(发现依赖 B)
// -> 创建 B
// -> 实例化 B
// -> 提前暴露 B
// -> 注入 B 的属性(发现依赖 A)
// -> 从提前暴露缓存获取 A(半成品)
// -> B 创建完成
// -> 设置 A.b = B
// 4. A 创建完成
核心代码:
private Object doGetBean(String beanName) throws Exception {
// 先从提前暴露缓存获取
Object bean = getEarlyExposeBean(beanName);
if (bean != null) {
return bean;
}
// 创建实例
Object instance = createBeanInstance(bd);
// 提前暴露(解决循环依赖的关键)
if (bd.isSingleton()) {
doEarlyExpose(beanName, instance);
}
// 属性注入
setPropertyDIValues(bd, instance);
return instance;
}
四、完整实现与测试
完整类图
┌─────────────────────────────────────────────────────────────┐
│ BeanFactory │
│ + getBean(String): Object │
│ + registerBeanDefinition(String, BeanDefinition): void │
└──────────────────────────┬──────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ DefaultBeanFactory │
│ │
│ - beanDefinitionMap: Map<String, BeanDefinition> │
│ - singletonObjects: Map<String, Object> │
│ - buildingBeans: ThreadLocal<Set<String>> │
│ - earlyExposeBeans: ThreadLocal<Map<String, Object>> │
│ │
│ + doGetBean(String): Object │
│ + createBeanInstance(BeanDefinition): Object │
│ + setPropertyDIValues(BeanDefinition, Object): void │
│ + determineConstructor(BeanDefinition, Object[]): Constructor│
└─────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────┐
│ BeanDefinition │
│ + getBeanClass(): Class<?> │
│ + getConstructorArgumentValues(): List<?> │
│ + getPropertyValues(): List<PropertyValue> │
│ + isSingleton(): boolean │
└──────────────────────────┬──────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ GenericBeanDefinition │
│ - beanClass: Class<?> │
│ - constructorArgumentValues: List<?> │
│ - propertyValues: List<PropertyValue> │
│ - singleton: boolean │
└─────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────┐
│ BeanReference │
│ - beanName: String │
│ - beanType: Class<?> │
└─────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────┐
│ PropertyValue │
│ - name: String │
│ - value: Object │
└─────────────────────────────────────────────────────────────┘
测试用例
public class DITest {
@Test
public void testConstructorDI() throws Exception {
DefaultBeanFactory factory = new DefaultBeanFactory();
// 注册 CBean
GenericBeanDefinition cDef = new GenericBeanDefinition();
cDef.setBeanClass(CBean.class);
cDef.setPropertyValues(Arrays.asList(
new PropertyValue("name", "CBean")
));
factory.registerBeanDefinition("cbean", cDef);
// 注册 ABean,构造器注入
GenericBeanDefinition aDef = new GenericBeanDefinition();
aDef.setBeanClass(ABean.class);
aDef.setConstructorArgumentValues(Arrays.asList(
"abean01",
new BeanReference("cbean")
));
factory.registerBeanDefinition("abean", aDef);
// 获取并测试
ABean aBean = (ABean) factory.getBean("abean");
assertNotNull(aBean);
assertEquals("abean01", aBean.getName());
assertNotNull(aBean.getCBean());
assertEquals("CBean", aBean.getCBean().getName());
}
@Test
public void testPropertyDI() throws Exception {
DefaultBeanFactory factory = new DefaultBeanFactory();
// 注册 Boy
GenericBeanDefinition boyDef = new GenericBeanDefinition();
boyDef.setBeanClass(Boy.class);
boyDef.setPropertyValues(Arrays.asList(
new PropertyValue("name", "小明")
));
factory.registerBeanDefinition("boy", boyDef);
// 注册 Girl,属性注入
GenericBeanDefinition girlDef = new GenericBeanDefinition();
girlDef.setBeanClass(Girl.class);
girlDef.setPropertyValues(Arrays.asList(
new PropertyValue("name", "小丽"),
new PropertyValue("age", 20),
new PropertyValue("boyfriend", new BeanReference("boy"))
));
factory.registerBeanDefinition("girl", girlDef);
// 获取并测试
Girl girl = (Girl) factory.getBean("girl");
assertNotNull(girl);
assertEquals("小丽", girl.getName());
assertEquals(20, girl.getAge());
assertNotNull(girl.getBoyfriend());
assertEquals("小明", girl.getBoyfriend().getName());
}
@Test
public void testCircularDependency() throws Exception {
DefaultBeanFactory factory = new DefaultBeanFactory();
// A 依赖 B
GenericBeanDefinition aDef = new GenericBeanDefinition();
aDef.setBeanClass(A.class);
aDef.setPropertyValues(Arrays.asList(
new PropertyValue("b", new BeanReference("b"))
));
factory.registerBeanDefinition("a", aDef);
// B 依赖 A
GenericBeanDefinition bDef = new GenericBeanDefinition();
bDef.setBeanClass(B.class);
bDef.setPropertyValues(Arrays.asList(
new PropertyValue("a", new BeanReference("a"))
));
factory.registerBeanDefinition("b", bDef);
// 获取 A(循环依赖应该被解决)
A a = (A) factory.getBean("a");
assertNotNull(a);
assertNotNull(a.getB());
assertNotNull(a.getB().getA());
assertEquals(a, a.getB().getA()); // 是同一个 A
}
}
五、总结与思考
核心知识点回顾
1. 依赖注入的本质
- 给 Bean 的成员变量赋值
- 构造器注入:通过构造方法参数赋值
- 属性注入:通过反射给字段赋值
2. BeanReference 设计
- 区分直接值和 Bean 依赖
- 支持按名称或按类型依赖
- 递归解析 Bean 依赖
3. 构造器注入实现
- 存储构造参数(List)
- 推断匹配的构造方法
- 处理构造参数中的 BeanReference
4. 属性注入实现
- PropertyValue 封装属性和值
- 反射设置字段值
- 提前暴露解决循环依赖
5. 循环依赖处理
- 构造器循环依赖:无法解决(实例化时需要完整依赖)
- 属性循环依赖:可以解决(提前暴露半成品对象)
与 Spring 源码的对比
| 功能 | 手写实现 | Spring 源码 |
|---|---|---|
| BeanReference | BeanReference 类 | RuntimeBeanReference |
| 属性封装 | PropertyValue 类 | PropertyValue 类 |
| 构造器推断 | 简单遍历匹配 | ConstructorResolver(复杂算法) |
| 循环依赖 | 简单提前暴露 | 三级缓存(singletonFactories、earlySingletonObjects、singletonObjects) |
| 代理支持 | 无 | AOP 代理对象提前暴露 |
学习建议
- 动手实践:自己实现一遍,加深理解
- 对比源码:与 Spring 源码对比,学习优化技巧
- 思考问题:
- 为什么构造器注入无法解决循环依赖?
- 提前暴露为什么能解决属性循环依赖?
- Spring 的三级缓存是如何工作的?
- 扩展练习:
- 支持注解配置(
@Autowired、@Value) - 实现 Setter 方法注入
- 实现 AOP 代理功能
- 支持注解配置(
扩展作业
条件依赖配置支持:
在 Bean 定义配置中可以指定它条件依赖某些 Bean 或类,当这些 Bean 或类存在时,这个 Bean 的配置才能生效。
// 示例:只有当 DataSource Bean 存在时,才创建 JdbcTemplate
GenericBeanDefinition jdbcTemplateDef = new GenericBeanDefinition();
jdbcTemplateDef.setBeanClass(JdbcTemplate.class);
jdbcTemplateDef.setDependsOn("dataSource"); // 条件依赖
factory.registerBeanDefinition("jdbcTemplate", jdbcTemplateDef);
相关资源
- Spring 官方文档:https://docs.spring.io/spring-framework/docs/current/reference/html/core.html
- Spring 源码:https://github.com/spring-projects/spring-framework
- 相关书籍:《Spring 源码深度解析》、《Spring 技术内幕》
如果本文对你有帮助,欢迎点赞、收藏、关注!如有疑问,欢迎在评论区留言讨论。
关键词:Spring 源码, 依赖注入, DI, IoC 容器, 手写框架, 循环依赖, 构造器注入, 属性注入, Java 反射, BeanReference
本文是手写 Spring 框架系列第二篇,第一篇实现了 IoC 容器的基础功能,本篇实现了 DI 依赖注入功能,敬请期待后续文章…

:从原理到实现,彻底搞懂 IoC 容器核心&spm=1001.2101.3001.5002&articleId=161264341&d=1&t=3&u=355ac0dd34b5445bb60ad7312443c801)
87万+

被折叠的 条评论
为什么被折叠?



