Spring 源码解析:prepareBeanFactory() 方法深度剖析与面试指南

163 阅读4分钟

Spring 源码解析:prepareBeanFactory() 方法深度剖析与面试指南

引言

在 Spring 容器初始化的 refresh() 方法中,prepareBeanFactory()obtainFreshBeanFactory() 后的关键步骤。它负责对 BeanFactory 进行基础配置,为后续的 Bean 实例化和依赖注入提供支持。本文通过源码逐行解析 prepareBeanFactory(),并总结高频面试考点。


一、prepareBeanFactory() 方法的作用

prepareBeanFactory()BeanFactory 初始化后的核心配置阶段,主要完成以下任务:

  1. 设置 BeanFactory 的基础属性(如类加载器、表达式解析器)。
  2. 注册环境相关的单例 Bean(如 Environment、系统属性、系统环境变量)。
  3. 添加 ApplicationContextAwareProcessor,处理 Aware 接口的回调。
  4. 忽略特定接口的自动注入(如 EnvironmentAwareApplicationContextAware)。
  5. 注册可解析的依赖(如 BeanFactoryApplicationContext)。
  6. 添加 ApplicationListenerDetector,检测并管理 ApplicationListener Bean。

二、源码逐行解析

1. 方法入口与核心逻辑
protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
    // 1. 设置类加载器
    beanFactory.setBeanClassLoader(getClassLoader());
    // 2. 设置表达式解析器(SPEL)
    beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
    // 3. 注册属性编辑器注册器(用于类型转换)
    beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));

    // 4. 添加 ApplicationContextAwareProcessor
    beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
    // 5. 忽略 Aware 接口的自动注入(由 Spring 容器处理)
    beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
    beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
    beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
    beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
    beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
    beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);

    // 6. 注册可解析的依赖(允许直接注入 BeanFactory 或 ApplicationContext)
    beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
    beanFactory.registerResolvableDependency(ResourceLoader.class, this);
    beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
    beanFactory.registerResolvableDependency(ApplicationContext.class, this);

    // 7. 添加 ApplicationListenerDetector
    beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));

    // 8. 注册环境相关的单例 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());
    }
}
2. 关键操作详解
  • 类加载器与表达式解析器

    • setBeanClassLoader:确保 Bean 实例化时使用容器指定的类加载器。
    • setBeanExpressionResolver:支持 SPEL 表达式(如 #{...})的解析。
  • ApplicationContextAwareProcessor

    • 作用:处理 Aware 接口(如 BeanNameAwareApplicationContextAware)的回调,在 Bean 初始化时注入相关依赖。
    • 实现原理:通过 postProcessBeforeInitialization 方法调用 invokeAwareInterfaces()
  • 忽略 Aware 接口的自动注入

    • 避免用户手动注入 ApplicationContextAware 等接口的实现,这些接口由 Spring 容器自动处理。
  • 可解析的依赖注册

    • 允许通过 @Autowired 直接注入 BeanFactoryApplicationContext,例如:
      @Autowired
      private ApplicationContext context;
      
  • ApplicationListenerDetector

    • 检测实现了 ApplicationListener 接口的 Bean,并将其注册到容器的事件广播器中。
  • 环境相关单例注册

    • Environment、系统属性、系统环境变量注册为单例 Bean,便于通过名称直接访问。

三、高频面试考点与答案

1. prepareBeanFactory() 的核心作用是什么?
  • 答案:配置 BeanFactory 的基础属性(类加载器、表达式解析器),注册关键组件(如 Aware 处理器、环境 Bean),为后续 Bean 实例化和依赖注入提供支持。
2. ApplicationContextAwareProcessor 的作用是什么?
  • 答案:在 Bean 初始化前处理 Aware 接口的回调,例如为实现了 ApplicationContextAware 的 Bean 注入 ApplicationContext
3. 为什么需要调用 ignoreDependencyInterface() 方法?
  • 答案:防止用户手动注入 Aware 接口的实现类(如 ApplicationContextAware),这些接口的依赖由 Spring 容器自动处理。
4. 如何在 Bean 中直接注入 ApplicationContext
  • 答案:通过 @Autowired 注入,因为 ApplicationContext 已被注册为可解析的依赖。
5. ApplicationListenerDetector 的职责是什么?
  • 答案:检测实现了 ApplicationListener 的 Bean,并将其添加到容器的事件广播器中,确保事件监听功能生效。
6. 如何扩展 BeanFactory 的配置?
  • 答案:通过重写 prepareBeanFactory() 方法,例如添加自定义的 BeanPostProcessor 或注册新的可解析依赖。

四、总结与扩展

  • 设计模式ApplicationContextAwareProcessor 体现了回调机制BeanPostProcessor 是典型的拦截器模式
  • 环境集成:通过注册 Environment 和系统属性,Spring 实现了配置的统一管理。
  • 扩展性:开发者可通过自定义 BeanPostProcessor 或重写 prepareBeanFactory() 方法扩展容器行为。

附:典型面试题

Q: 如果自定义的 Aware 接口需要被 Spring 处理,应该怎么做?
A: 实现 BeanPostProcessor,在 postProcessBeforeInitialization 方法中手动调用接口方法。

Q: 为什么 ApplicationContext 可以被直接注入到 Bean 中?
A: 因为 prepareBeanFactory() 中通过 registerResolvableDependency() 将其注册为可解析的依赖。

Q: 如何禁用 ApplicationContextAwareProcessor
A: 重写 prepareBeanFactory() 方法,移除默认添加的 ApplicationContextAwareProcessor(一般不推荐)。


通过深入理解 prepareBeanFactory(),开发者可以掌握 Spring 容器的初始化细节,灵活应对环境配置、依赖注入等场景。在面试中,结合源码和实际应用回答问题,将显著提升技术深度评价。