IOC 启动流程

Cyrus Huang / 2024-10-26 / 原文

初始化12步骤

容器创建会进入 refresh 方法,总共 12 个步骤

// org.springframework.context.support.AbstractApplicationContext#refresh
@Override
public void refresh() throws BeansException, IllegalStateException {
    synchronized (this.startupShutdownMonitor) {
        StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");

        // 步骤一:准备阶段
        prepareRefresh();

        // 步骤二:获得一个 BeanFactory(bean 定义信息在这一步会保存好)
        ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

        // 步骤三:给 BeanFactory 赋能
        prepareBeanFactory(beanFactory);

        try {
            // 步骤四:扩展 BeanFactory(这是个钩子方法,目的是留给子类的,子类可根据需要再次赋予 BeanFactory 更多能力)
            postProcessBeanFactory(beanFactory);

            StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");
            
            // 步骤五:执行 BeanFactoryProPercessor
            invokeBeanFactoryPostProcessors(beanFactory);

            // Register bean processors that intercept bean creation.
            registerBeanPostProcessors(beanFactory);
            beanPostProcess.end();

            // Initialize message source for this context.
            initMessageSource();

            // Initialize event multicaster for this context.
            initApplicationEventMulticaster();

            // Initialize other special beans in specific context subclasses.
            onRefresh();

            // Check for listener beans and register them.
            registerListeners();

            // Instantiate all remaining (non-lazy-init) singletons.
            finishBeanFactoryInitialization(beanFactory);

            // Last step: publish corresponding event.
            finishRefresh();
        }
		...
    }
}

步骤1:准备容器

// org.springframework.context.support.AbstractApplicationContext#prepareRefresh
protected void prepareRefresh() {
    // 计时
    this.startupDate = System.currentTimeMillis();
    this.closed.set(false);
    this.active.set(true);

    // 这是一个模板方法,子类复写自定义配置 spring 信息,MVC、Boot、Cloud 等很多框架都复写过
    initPropertySources();

    // 必要参数验证
    getEnvironment().validateRequiredProperties();

    // 初始化事件监听器和事件,都置为空列表
    if (this.earlyApplicationListeners == null) {
        this.earlyApplicationListeners = new LinkedHashSet<>(this.applicationListeners);
    }
    else {
        this.applicationListeners.clear();
        this.applicationListeners.addAll(this.earlyApplicationListeners);
    }
    this.earlyApplicationEvents = new LinkedHashSet<>();
}

步骤2:获得 BeanFactory

  • 产生一个新鲜的 BeanFactory
  • 保存好 bean 定义信息

ApplicationContext 一般叫容器,BeanFactory 是真正保存 bean 的地方

// org.springframework.context.support.AbstractApplicationContext#obtainFreshBeanFactory
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
    refreshBeanFactory();
    return getBeanFactory();
}

// org.springframework.context.support.AbstractRefreshableApplicationContext#refreshBeanFactory
@Override
protected final void refreshBeanFactory() throws BeansException {
    if (hasBeanFactory()) {
        destroyBeans();
        closeBeanFactory();
    }
    try {
        DefaultListableBeanFactory beanFactory = createBeanFactory();
        beanFactory.setSerializationId(getId());
        customizeBeanFactory(beanFactory);
        // 这里会把 bean 定义信息准备好
        loadBeanDefinitions(beanFactory);
        this.beanFactory = beanFactory;
    }
    catch (IOException ex) {
        throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
    }
}

步骤3:初始化 BeanFactory

上一步刚初始化了 BeanFactory,还没什么能力,这一步是配置 BeanFactory 的属性,让其具有处理某些动作的能力

当遇到相关动作,就会使用这里赋予的能力,所以这里代码比较简单,就是给不同属性赋值

  • 比如 addBeanPostProcessor 给 BeanFactory 添加了一些后置处理器
    • 加入到 beanPostProcessors 属性中
    • 比如 SPEL 解析器,各种 Aware 回调处理器
  • 比如 ignoreDependencyInterface 忽略了一些自动装配的类
    • 加入到 ignoredDependencyInterfaces 属性中
    • 1,这些接口的实现类的属性@Autowired 不生效(不能注入别的 bean)
    • 2,别的 bean 里也使用 @Autowired 给属性赋值也不生效(不能被别的 bean 注入)
  • 比如 registerResolvableDependency 提前放入一些可能需要别的依赖的 bean
    • 是加入到 resolvableDependencies 属性中
    • 这一步是为了提升效率的,如果不提前放,后面找到这些 bean 也会放进去(事先就放进去)
// org.springframework.context.support.AbstractApplicationContext#prepareBeanFactory
protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
    // 类加载器
    beanFactory.setBeanClassLoader(getClassLoader());
    
    // 是否不解析 SPEL,spring.spel.ignore 配置项来控制
    if (!shouldIgnoreSpel) { 
        // StandardBeanExpressionResolver:SPEL 表达式解析器
        beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
    }
    
    // ResourceEditorRegistrar:用于把配置文件转成一个 Resource 对象
    beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));

    // 添加后置处理器,如果有 bean 实现了 ApplicationContextAware,BeanFactory 使用 ApplicationContextAwareProcessor 去处理
    beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
    
    // 忽略一些自动装配
    beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
    beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
    beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
    beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
    beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
    beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);
    beanFactory.ignoreDependencyInterface(ApplicationStartupAware.class);

    // 这些注册为 bean,比如可以直接 @Autorired BeanFactory beanFactory 来注入 BeanFactory
    beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
    beanFactory.registerResolvableDependency(ResourceLoader.class, this);
    beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
    beanFactory.registerResolvableDependency(ApplicationContext.class, this);

    // 添加后置处理器,让 BeanFactory 可以处理时间发布与监听
    beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));

    // GraalVM 支持,java 虚拟机一般都是 hotspot VM
    if (!NativeDetector.inNativeImage() && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
        beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
        beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
    }

    // 再实现注册一些默认的 bean
    if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {
        beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());
    }
    if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {
        beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());
    }
    if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {
        beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());
    }
    if (!beanFactory.containsLocalBean(APPLICATION_STARTUP_BEAN_NAME)) {
        beanFactory.registerSingleton(APPLICATION_STARTUP_BEAN_NAME, getApplicationStartup());
    }
}

步骤4:扩展 BeanFactory

上一步已经赋能了,这里再次赋能,这是一个钩子方法,没有实现,所以专门提供给子类的

比如 SpringMVC 扩展后我们标注 @Controller 就会把这个 bean 注入到容器中

步骤5:执行 BeanFactoryPostProcesser

步骤 3 给 BeanFactory 放入了一批后置处理器,这一步就是要执行他们

// org.springframework.context.support.AbstractApplicationContext#invokeBeanFactoryPostProcessors
protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
    // this.getBeanFactoryPostProcessors() 就是获取所有 bean 工厂后置处理器,此时是空的 invokeBeanFactoryPostProcessors 会去找
    // invokeBeanFactoryPostProcessors 首先找到所有实现了 BeanFactoryPostProcessor 接口的 bean,然后挨个调用其 postProcessBeanFactory 方法
    // BeanFactoryPostProcessor 干嘛的?修改 bean 定义的,在创建前对 bean 定义做一些修改,后续根据修改后的定义来创建 bean
    PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, this.getBeanFactoryPostProcessors());
    // GraalVM 支持
    if (!NativeDetector.inNativeImage() && beanFactory.getTempClassLoader() == null && beanFactory.containsBean("loadTimeWeaver")) {
        beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
        beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
    }
}

// org.springframework.context.support.PostProcessorRegistrationDelegate#invokeBeanFactoryPostProcessors(org.springframework.beans.factory.config.ConfigurableListableBeanFactory, java.util.List<org.springframework.beans.factory.config.BeanFactoryPostProcessor>)
public static void invokeBeanFactoryPostProcessors(
        ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {
    ...
    List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
    List<String> orderedPostProcessorNames = new ArrayList<>();
    List<String> nonOrderedPostProcessorNames = new ArrayList<>();
    for (String ppName : postProcessorNames) {
        if (processedBeans.contains(ppName)) {
            // skip - already processed in first phase above
        }
        else if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
            // 找到所有实现了 BeanFactoryPostProcessor 的类
            priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));
        }
        else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
            orderedPostProcessorNames.add(ppName);
        }
        else {
            nonOrderedPostProcessorNames.add(ppName);
        }
    }
    ...
}