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通过巧妙的缓存机制和生命周期管理,解决了诸如循环依赖等复杂问题,同时提供了足够的扩展性来满足各种定制需求。

相关推荐
蓝澈112129 分钟前
迪杰斯特拉算法之解决单源最短路径问题
java·数据结构
Kali_0736 分钟前
使用 Mathematical_Expression 从零开始实现数学题目的作答小游戏【可复制代码】
java·人工智能·免费
rzl021 小时前
java web5(黑马)
java·开发语言·前端
时序数据说1 小时前
为什么时序数据库IoTDB选择Java作为开发语言
java·大数据·开发语言·数据库·物联网·时序数据库·iotdb
君爱学习1 小时前
RocketMQ延迟消息是如何实现的?
后端
guojl1 小时前
深度解读jdk8 HashMap设计与源码
java
Falling421 小时前
使用 CNB 构建并部署maven项目
后端
guojl1 小时前
深度解读jdk8 ConcurrentHashMap设计与源码
java
程序员小假1 小时前
我们来讲一讲 ConcurrentHashMap
后端