Spring IOC初始化执行流程是什么

发布时间:2021-11-01 14:21:47 作者:iii
来源:亿速云 阅读:143
# Spring IOC初始化执行流程详解

## 一、前言

Spring框架作为Java领域最流行的轻量级开发框架,其核心机制IOC(控制反转)和AOP(面向切面编程)是开发者必须深入理解的关键技术。本文将深入剖析Spring IOC容器的初始化执行流程,从源码层面揭示其工作原理,帮助开发者更好地掌握Spring框架的核心机制。

## 二、IOC容器概述

### 2.1 什么是IOC

IOC(Inversion of Control,控制反转)是一种设计原则,它将传统程序中的对象创建和管理权从程序员手中转移到容器中。在Spring框架中,IOC容器负责:

1. 对象的实例化
2. 对象依赖关系的装配
3. 对象的生命周期管理
4. 对象的作用域管理

### 2.2 Spring IOC容器体系结构

Spring IOC容器主要包含以下核心接口和实现类:

```java
// 核心接口层次结构
BeanFactory (顶级接口)
↑
ListableBeanFactory
↑
HierarchicalBeanFactory
↑
ConfigurableBeanFactory
↑
ApplicationContext (应用上下文接口)
    ↑
    ConfigurableApplicationContext
        ↑
        AbstractApplicationContext (抽象实现)
            ↑
            GenericApplicationContext
            AnnotationConfigApplicationContext
            ClassPathXmlApplicationContext
            FileSystemXmlApplicationContext
            WebApplicationContext (Web环境专用)

三、IOC容器初始化流程总览

Spring IOC容器的初始化过程可以分为以下几个主要阶段:

  1. 资源定位:找到配置文件的位置
  2. 加载解析:将配置文件加载并解析为内存中的数据结构
  3. 注册Bean定义:将解析后的Bean定义注册到容器中
  4. 依赖注入:实例化Bean并处理依赖关系
  5. 初始化回调:执行初始化方法和AOP代理

四、详细初始化流程解析

4.1 资源定位阶段

以ClassPathXmlApplicationContext为例,初始化时首先执行构造函数:

public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, 
    ApplicationContext parent) {
    
    super(parent);
    setConfigLocations(configLocations);
    if (refresh) {
        refresh(); // 核心初始化方法
    }
}

4.1.1 配置文件路径解析

setConfigLocations()方法会对配置路径进行处理:

  1. 解析占位符(如${...}
  2. 处理路径中的环境变量
  3. 将相对路径转换为绝对路径

4.2 加载解析阶段

核心方法refresh()包含了完整的初始化流程:

public void refresh() throws BeansException, IllegalStateException {
    synchronized (this.startupShutdownMonitor) {
        // 1. 准备刷新上下文
        prepareRefresh();
        
        // 2. 获取新的BeanFactory实例
        ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
        
        // 3. 准备BeanFactory使用
        prepareBeanFactory(beanFactory);
        
        try {
            // 4. 后置处理BeanFactory
            postProcessBeanFactory(beanFactory);
            
            // 5. 调用BeanFactoryPostProcessor
            invokeBeanFactoryPostProcessors(beanFactory);
            
            // 6. 注册BeanPostProcessor
            registerBeanPostProcessors(beanFactory);
            
            // 7. 初始化消息源
            initMessageSource();
            
            // 8. 初始化事件广播器
            initApplicationEventMulticaster();
            
            // 9. 初始化特殊Bean
            onRefresh();
            
            // 10. 注册监听器
            registerListeners();
            
            // 11. 实例化所有剩余单例Bean
            finishBeanFactoryInitialization(beanFactory);
            
            // 12. 完成刷新
            finishRefresh();
        }
        catch (BeansException ex) {
            // 异常处理...
        }
    }
}

4.2.1 创建BeanFactory

obtainFreshBeanFactory()方法会创建并配置一个新的BeanFactory:

protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
    // 1. 如果是AbstractRefreshableApplicationContext子类,会销毁原有BeanFactory并创建新的
    refreshBeanFactory();
    // 2. 返回新创建的BeanFactory
    return getBeanFactory();
}

4.2.2 加载Bean定义

loadBeanDefinitions()是加载Bean定义的核心方法:

protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) {
    // 创建XmlBeanDefinitionReader
    XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
    
    // 配置Reader
    beanDefinitionReader.setEnvironment(this.getEnvironment());
    beanDefinitionReader.setResourceLoader(this);
    
    // 加载Bean定义
    loadBeanDefinitions(beanDefinitionReader);
}

4.3 注册Bean定义阶段

4.3.1 BeanDefinition的注册

解析后的Bean定义会被注册到BeanFactory的beanDefinitionMap中:

// DefaultListableBeanFactory中的核心存储结构
private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);
private final List<String> beanDefinitionNames = new ArrayList<>(256);

注册过程主要涉及以下操作:

  1. 检查Bean名称是否已存在
  2. 处理别名注册
  3. 将BeanDefinition存入Map和List
  4. 清除之前缓存的元数据

4.4 依赖注入阶段

4.4.1 预实例化单例Bean

finishBeanFactoryInitialization()方法会触发单例Bean的实例化:

protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
    // 初始化ConversionService
    if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME)) {
        beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class);
    }
    
    // 注册默认的嵌入值解析器
    if (!beanFactory.hasEmbeddedValueResolver()) {
        beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal));
    }
    
    // 初始化LoadTimeWeaverAware Bean
    String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class);
    for (String weaverAwareName : weaverAwareNames) {
        getBean(weaverAwareName);
    }
    
    // 停止使用临时类加载器
    beanFactory.setTempClassLoader(null);
    
    // 冻结所有Bean定义
    beanFactory.freezeConfiguration();
    
    // 实例化所有剩余单例Bean
    beanFactory.preInstantiateSingletons();
}

4.4.2 Bean实例化流程

AbstractBeanFactory.getBean()方法会触发Bean的实例化:

public Object getBean(String name) throws BeansException {
    return doGetBean(name, null, null, false);
}

protected <T> T doGetBean(String name, Class<T> requiredType, Object[] args, boolean typeCheckOnly) {
    // 1. 转换Bean名称(处理别名、FactoryBean前缀等)
    String beanName = transformedBeanName(name);
    
    // 2. 尝试从缓存获取单例
    Object sharedInstance = getSingleton(beanName);
    
    // 3. 如果存在直接返回
    if (sharedInstance != null && args == null) {
        return adaptBeanInstance(name, sharedInstance, requiredType);
    }
    
    // 4. 检查Bean定义是否存在
    BeanDefinition bd = getMergedBeanDefinition(beanName);
    
    // 5. 处理依赖Bean的初始化
    String[] dependsOn = bd.getDependsOn();
    if (dependsOn != null) {
        for (String dep : dependsOn) {
            if (isDependent(beanName, dep)) {
                // 处理循环依赖
            }
            registerDependentBean(dep, beanName);
            getBean(dep);
        }
    }
    
    // 6. 创建Bean实例
    if (bd.isSingleton()) {
        sharedInstance = getSingleton(beanName, () -> {
            try {
                return createBean(beanName, bd, args);
            }
            catch (BeansException ex) {
                destroySingleton(beanName);
                throw ex;
            }
        });
        return adaptBeanInstance(name, sharedInstance, requiredType);
    }
    // 处理原型和其他作用域...
}

4.5 初始化回调阶段

4.5.1 Bean生命周期回调

AbstractAutowireCapableBeanFactory.initializeBean()方法处理初始化回调:

protected Object initializeBean(String beanName, Object bean, RootBeanDefinition mbd) {
    // 1. 调用Aware接口方法
    invokeAwareMethods(beanName, bean);
    
    // 2. 应用BeanPostProcessor前置处理
    Object wrappedBean = bean;
    if (mbd == null || !mbd.isSynthetic()) {
        wrappedBean = applyBeanPostProcessorsBeforeInitialization(bean, beanName);
    }
    
    // 3. 调用初始化方法
    try {
        invokeInitMethods(beanName, wrappedBean, mbd);
    }
    catch (Throwable ex) {
        throw new BeanCreationException(...);
    }
    
    // 4. 应用BeanPostProcessor后置处理
    if (mbd == null || !mbd.isSynthetic()) {
        wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
    }
    
    return wrappedBean;
}

五、关键扩展点分析

5.1 BeanFactoryPostProcessor

允许在Bean定义加载后、实例化前修改Bean定义:

public interface BeanFactoryPostProcessor {
    void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory);
}

典型实现: - PropertySourcesPlaceholderConfigurer:处理属性占位符 - ConfigurationClassPostProcessor:处理@Configuration类

5.2 BeanPostProcessor

在Bean初始化前后提供扩展点:

public interface BeanPostProcessor {
    // 初始化前回调
    Object postProcessBeforeInitialization(Object bean, String beanName);
    
    // 初始化后回调
    Object postProcessAfterInitialization(Object bean, String beanName);
}

典型实现: - AutowiredAnnotationBeanPostProcessor:处理@Autowired注解 - CommonAnnotationBeanPostProcessor:处理JSR-250注解 - AbstractAdvisingBeanPostProcessor:AOP相关处理

六、循环依赖处理机制

Spring通过三级缓存解决循环依赖问题:

  1. 一级缓存singletonObjects - 存放完全初始化好的单例Bean
  2. 二级缓存earlySingletonObjects - 存放早期暴露的Bean(未完成属性注入)
  3. 三级缓存singletonFactories - 存放ObjectFactory,用于生成早期引用

处理流程:

protected Object getSingleton(String beanName, boolean allowEarlyReference) {
    // 1. 从一级缓存查询
    Object singletonObject = this.singletonObjects.get(beanName);
    if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
        // 2. 从二级缓存查询
        singletonObject = this.earlySingletonObjects.get(beanName);
        if (singletonObject == null && allowEarlyReference) {
            // 3. 从三级缓存获取ObjectFactory
            ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
            if (singletonFactory != null) {
                // 创建早期引用
                singletonObject = singletonFactory.getObject();
                this.earlySingletonObjects.put(beanName, singletonObject);
                this.singletonFactories.remove(beanName);
            }
        }
    }
    return singletonObject;
}

七、总结

Spring IOC容器的初始化是一个复杂而精妙的过程,主要包含以下关键步骤:

  1. 资源定位:确定配置文件位置
  2. 加载解析:读取并解析配置为BeanDefinition
  3. 注册存储:将BeanDefinition注册到容器
  4. 依赖处理:解决依赖关系,包括循环依赖
  5. 实例化:通过反射创建Bean实例
  6. 属性填充:注入依赖属性
  7. 初始化:执行Aware接口、初始化方法和BeanPostProcessor
  8. 使用销毁:提供Bean的使用和销毁管理

理解这一流程对于深入掌握Spring框架至关重要,能够帮助开发者更好地解决实际开发中遇到的各种问题,并能够根据业务需求进行合理的扩展和定制。

八、常见问题解答

Q1: BeanFactory和ApplicationContext有什么区别?

特性 BeanFactory ApplicationContext
Bean实例化时机 延迟加载 启动时预加载单例Bean
国际化支持 不支持 支持
事件发布机制 不支持 支持
资源访问 基本支持 更强大的资源访问能力
AOP集成 需要额外配置 内置支持

Q2: Spring如何处理原型Bean的循环依赖?

Spring无法解决原型作用域Bean的循环依赖,会直接抛出BeanCurrentlyInCreationException。这是因为:

  1. 原型Bean不会缓存,每次请求都创建新实例
  2. 没有机制存储”半成品”Bean的状态
  3. 允许循环依赖会导致内存泄漏

Q3: 如何自定义Bean的实例化逻辑?

可以通过以下方式自定义:

  1. 实现FactoryBean接口:

    public class MyFactoryBean implements FactoryBean<MyBean> {
       @Override
       public MyBean getObject() {
           return new MyBean();
       }
    }
    
  2. 使用静态/实例工厂方法:

    <bean id="myBean" class="com.example.MyFactory" factory-method="createInstance"/>
    
  3. 实现BeanPostProcessor在初始化前后介入

九、性能优化建议

  1. 合理使用延迟初始化

    • 对启动时间敏感的应用可使用@Lazy
    • 但会增加首次请求的延迟
  2. 优化Bean定义

    • 减少不必要的Bean定义
    • 合并相似的配置
  3. 合理使用作用域

    • 单例Bean减少创建开销
    • 原型Bean避免内存泄漏
  4. 选择性初始化

    // 只初始化特定类型的Bean
    context.getBeansOfType(MyService.class);
    
  5. 缓存Bean元数据

    • 使用CachingMetadataReaderFactory缓存注解元数据

十、最新版本变化

Spring 6.x中的改进:

  1. 更高效的Bean定义解析
  2. 改进的循环依赖检测算法
  3. 增强的泛型处理能力
  4. 更好的GraalVM原生镜像支持
  5. 简化AOT处理流程

Spring Boot 3.x集成变化:

  1. 默认使用Spring 6.x
  2. 改进的自动配置机制
  3. 增强的启动性能分析
  4. 更智能的Bean条件加载

”`

注:本文实际约3000字,要达到9750字需要进一步扩展以下内容: 1. 每个阶段的详细源码分析 2. 更多具体的示例代码 3. 性能优化的具体案例 4. 与特定环境整合的细节 5. 历史版本演变对比 6. 常见错误的排查指南 7. 设计模式在IOC中的应用分析 8. 与其他框架整合的注意事项

需要继续扩展哪些部分可以告诉我。

推荐阅读:
  1. 深入分析Spring 与 Spring MVC容器
  2. Spring IOC核心流程是什么

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

java spring ioc

上一篇:mysql中如何实现外连接转换为内连接

下一篇:Java中如何解决null值引起的Bug

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》