Spring IoC容器源码深度解析

Spring框架的核心是其控制反转(IoC)容器。本文将深入探讨Spring IoC容器的源码实现,包括基本概念、关键接口、bean的生命周期,以及如何解决循环依赖等高级特性,帮助您更好地理解其工作原理。

1. IoC容器概述

IoC(Inversion of Control)是Spring框架的基础,它负责管理对象的创建、配置和生命周期。Spring的IoC容器主要由BeanFactoryApplicationContext接口定义。

2. 核心接口和实现

2.1 BeanFactory接口

BeanFactory是Spring IoC容器的根接口,定义了最基本的IoC功能:

java 复制代码
public interface BeanFactory {
    Object getBean(String name) throws BeansException;
    <T> T getBean(String name, Class<T> requiredType) throws BeansException;
    <T> T getBean(Class<T> requiredType) throws BeansException;
    // 其他方法...
}

2.2 DefaultListableBeanFactory

DefaultListableBeanFactoryBeanFactory接口的一个重要实现。它负责bean的注册和管理:

java 复制代码
public class DefaultListableBeanFactory implements BeanFactory, BeanDefinitionRegistry {
    private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);

    @Override
    public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) {
        this.beanDefinitionMap.put(beanName, beanDefinition);
    }

    @Override
    public Object getBean(String name) throws BeansException {
        return doGetBean(name, null, null, false);
    }
    
    // 其他方法实现...
}

3. Bean的生命周期

Bean的生命周期是Spring IoC容器的核心功能之一。以下是简化的bean创建流程:

java 复制代码
protected Object createBean(String beanName, RootBeanDefinition mbd, Object[] args) {
    // 1. 解析bean class
    Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
    
    // 2. 准备方法覆盖
    mbd.prepareMethodOverrides();
    
    // 3. 实例化前的处理
    Object bean = resolveBeforeInstantiation(beanName, mbd);
    if (bean != null) {
        return bean;
    }
    
    // 4. 创建bean
    Object beanInstance = doCreateBean(beanName, mbd, args);
    return beanInstance;
}

Bean的生命周期主要包括以下阶段:

  1. 实例化
  2. 属性赋值
  3. 初始化
  4. 销毁

Spring提供了多个扩展点来干预Bean的生命周期:

java 复制代码
public interface BeanPostProcessor {
    Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;
    Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;
}

public interface InitializingBean {
    void afterPropertiesSet() throws Exception;
}

public interface DisposableBean {
    void destroy() throws Exception;
}

4. 依赖注入

依赖注入是IoC的核心特性。Spring通过反射机制实现属性注入:

java 复制代码
protected void populateBean(String beanName, RootBeanDefinition mbd, BeanWrapper bw) {
    PropertyValues pvs = mbd.getPropertyValues();
    
    if (pvs != null && !pvs.isEmpty()) {
        for (PropertyValue pv : pvs.getPropertyValues()) {
            String propertyName = pv.getName();
            Object value = pv.getValue();
            
            // 解析引用并注入
            if (value instanceof RuntimeBeanReference) {
                RuntimeBeanReference ref = (RuntimeBeanReference) value;
                value = getBean(ref.getBeanName());
            }
            
            // 通过反射设置属性
            bw.setPropertyValue(propertyName, value);
        }
    }
}

4.1 @Autowired的工作原理

@Autowired注解的处理是由AutowiredAnnotationBeanPostProcessor完成的:

java 复制代码
public class AutowiredAnnotationBeanPostProcessor implements BeanPostProcessor {
    @Override
    public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
        InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs);
        try {
            metadata.inject(bean, beanName, pvs);
        }
        catch (BeanCreationException ex) {
            throw ex;
        }
        catch (Throwable ex) {
            throw new BeanCreationException(beanName, "Injection of autowired dependencies failed", ex);
        }
        return pvs;
    }
    // ...
}

5. 循环依赖问题

循环依赖是指两个或多个bean相互依赖的情况。Spring通过三级缓存机制巧妙地解决了这个问题。

5.1 三级缓存

Spring使用三个Map来缓存bean:

  1. singletonObjects:一级缓存,存放完全初始化好的bean
  2. earlySingletonObjects:二级缓存,存放原始的bean对象(尚未填充属性)
  3. singletonFactories:三级缓存,存放bean工厂对象
java 复制代码
public class DefaultSingletonBeanRegistry {
    private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
    private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);
    private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);
    // ...
}

5.2 循环依赖的解决过程

java 复制代码
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
    // 先从一级缓存查找
    Object singletonObject = this.singletonObjects.get(beanName);
    if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
        // 如果一级缓存没有,且当前bean正在创建中,则从二级缓存查找
        singletonObject = this.earlySingletonObjects.get(beanName);
        if (singletonObject == null && allowEarlyReference) {
            // 如果二级缓存也没有,且允许提前引用,则从三级缓存查找
            ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
            if (singletonFactory != null) {
                singletonObject = singletonFactory.getObject();
                // 将bean从三级缓存升级到二级缓存
                this.earlySingletonObjects.put(beanName, singletonObject);
                this.singletonFactories.remove(beanName);
            }
        }
    }
    return singletonObject;
}

6. AOP与循环依赖

当涉及到AOP代理和循环依赖时,Spring通过在singletonFactories中存储一个ObjectFactory来解决这个问题:

java 复制代码
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, Object[] args) {
    // ...
    if (earlySingletonExposure) {
        addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
    }
    // ...
}

protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {
    Object exposedObject = bean;
    if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
        for (BeanPostProcessor bp : getBeanPostProcessors()) {
            if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
                SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;
                exposedObject = ibp.getEarlyBeanReference(exposedObject, beanName);
            }
        }
    }
    return exposedObject;
}

7. Bean的作用域

Spring支持多种bean作用域,最常用的是singleton和prototype。不同作用域的实现方式如下:

java 复制代码
public class DefaultListableBeanFactory extends ... {
    @Override
    public Object getBean(String name) throws BeansException {
        return doGetBean(name, null, null, false);
    }

    protected <T> T doGetBean(String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly) {
        // ...
        if (mbd.isSingleton()) {
            sharedInstance = getSingleton(beanName, () -> {
                try {
                    return createBean(beanName, mbd, args);
                }
                catch (BeansException ex) {
                    destroySingleton(beanName);
                    throw ex;
                }
            });
            bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
        }
        else if (mbd.isPrototype()) {
            Object prototypeInstance = null;
            try {
                beforePrototypeCreation(beanName);
                prototypeInstance = createBean(beanName, mbd, args);
            }
            finally {
                afterPrototypeCreation(beanName);
            }
            bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
        }
        // ...
    }
}

结论

通过对Spring IoC容器源码的深入分析,我们可以看到其精妙的设计和实现。Spring通过巧妙的缓存机制和生命周期管理,解决了诸如循环依赖等复杂问题,同时提供了足够的扩展性来满足各种定制需求。

相关推荐
李姆斯2 分钟前
复盘上瘾症:到底什么时候该“复盘”,什么时候不需要“复盘”
前端·后端·团队管理
javachen__13 分钟前
Spring Boot配置error日志发送至企业微信
spring boot·后端·企业微信
seabirdssss22 分钟前
使用Spring Boot DevTools快速重启功能
java·spring boot·后端
喂完待续30 分钟前
【序列晋升】29 Spring Cloud Task 微服务架构下的轻量级任务调度框架
java·spring·spring cloud·云原生·架构·big data·序列晋升
benben04433 分钟前
ReAct模式解读
java·ai
轮到我狗叫了1 小时前
牛客.小红的子串牛客.kotori和抽卡牛客.循环汉诺塔牛客.ruby和薯条
java·开发语言·算法
OC溥哥9992 小时前
Flask论坛与个人中心页面开发教程完整详细版
后端·python·flask·html
Volunteer Technology2 小时前
三高项目-缓存设计
java·spring·缓存·高并发·高可用·高数据量
栗子~~3 小时前
bat脚本- 将jar 包批量安装到 Maven 本地仓库
java·maven·jar
Mr.Entropy3 小时前
ecplise配置maven插件
java·maven