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

相关推荐
星河梦瑾6 分钟前
SpringBoot相关漏洞学习资料
java·经验分享·spring boot·安全
黄名富9 分钟前
Redis 附加功能(二)— 自动过期、流水线与事务及Lua脚本
java·数据库·redis·lua
love静思冥想11 分钟前
JMeter 使用详解
java·jmeter
言、雲14 分钟前
从tryLock()源码来出发,解析Redisson的重试机制和看门狗机制
java·开发语言·数据库
TT哇21 分钟前
【数据结构练习题】链表与LinkedList
java·数据结构·链表
Yvemil71 小时前
《开启微服务之旅:Spring Boot 从入门到实践》(三)
java
Anna。。1 小时前
Java入门2-idea 第五章:IO流(java.io包中)
java·开发语言·intellij-idea
.生产的驴1 小时前
SpringBoot 对接第三方登录 手机号登录 手机号验证 微信小程序登录 结合Redis SaToken
java·spring boot·redis·后端·缓存·微信小程序·maven
爱上语文1 小时前
宠物管理系统:Dao层
java·开发语言·宠物
顽疲1 小时前
springboot vue 会员收银系统 含源码 开发流程
vue.js·spring boot·后端