目录

3.1Spring FrameWork的IOC容器

3.1.1BeanFactory继承结构

3.1.1.1BeanFactory根接口

3.1.1.2HierarchicalBeanFactory

3.1.1.3ListableBeanFactory

3.1.1.4AutowireCapaleBeanFactory

3.1.1.5ConfigurableBeanFactory

3.1.1.6AbstractBeanFactory

3.1.1.7AbstractAutowireCapableBeanFactory

3.1.1.8DefaultListableBeanFactory

3.1.2ApplictionContext

3.1.2.1ApplicationContext

3.1.2.2ConfigurableApplicationContext

3.1.2.3ApplicationContext的父接口

3.1.2.4AbstractApplicationContext

3.1.2.5GenericApplicationContext

3.1.2.6AnnotationConfigApplicationContext

3.1.2.7AbstractRefreshableApplicationContext

3.1.3扩展:BeanFactory和ApplicationContext的对比

3.2SpringBoot对IOC容器的扩展

3.3选用注解驱动IOC容器的原因

3.4重要概念补充一:Environment

3.4.1profile与property

3.4.2Environment的结构设计

3.4.2.1PropertyResolver

3.4.2.2ConfigurableEnvironment

3.4.2.3AbstractEnvironment

3.5重要概念补充二:BeanDefinition

3.5.1BeanDefination的基本定义及实现

3.5.2BeanDefinition的使用示例

3.6重要概念补充三:后置处理器

3.6.1 BeanDefinitionRegistryPostProceser

3.6.2 BeanFactoryPostProcessor

3.6.3BeanPostProcessor

3.1Spring FrameWork的IOC容器

org.springframework.beans和org.springframework.context包是Spring Framework的IOC容器的基础。

有关Spring Framework中的IOC容器模型,有一个ApplicationContext接口,不过不是顶层接口,还有一个父接口BeanFactory。BeanFactory接口是IOC容器的基础抽象,提供了一种高级配置机制,能够管理任何类型的对象。

ApplicationContext是BeanFactory的子接口,包含了BeanFactory的所有功能,且增加了以下几个特性:与Spring Framework的AOP和功能轻松集成;消息资源处理(用于国际化);事件发布;应用层特定的上下文,例如Web应用程序中使用的WebApplicationContext。

3.1.1BeanFactory继承结构

BeanFactory是IOC容器的顶层抽象,它仅定义最基础的bean对象的管理。BeanFactory及其派生接口的继承结构如下:

各个接口功能简要对比如下:

接口/类主要作用
BeanFactorySpring IoC 容器的根接口,提供基础的 Bean 获取能力
HierarchicalBeanFactory为容器提供父子层次结构支持,实现 Bean 作用域隔离与继承
ListableBeanFactory提供 Bean 的枚举和批量查询能力,支持按类型、注解查找
AutowireCapableBeanFactorySpring 的自动装配引擎,提供编程式的 Bean 创建和依赖注入
ConfigurableBeanFactoryBeanFactory 的配置中心,提供全方位的容器行为定制能力
ConfigurableListableBeanFactory功能最全的配置接口,组合了枚举、自动装配和配置能力
AbstractBeanFactoryBeanFactory 的骨架实现,提供通用的 Bean 获取流程模板
AbstractAutowireCapableBeanFactory自动装配的具体实现者,处理 Bean 实例化、依赖注入和初始化
DefaultListableBeanFactorySpring 默认的完整 BeanFactory 实现,具备所有容器功能

代码示例如下:

// ==================== 核心接口继承关系 ====================
// 1. 根接口
public interface BeanFactory {
    // 基础Bean获取方法
}
// 2. 层次结构支持
public interface HierarchicalBeanFactory extends BeanFactory {
    BeanFactory getParentBeanFactory();
    boolean containsLocalBean(String name);
}
// 3. 枚举和批量查询支持  
public interface ListableBeanFactory extends BeanFactory {
    String[] getBeanDefinitionNames();
    <T> Map<String, T> getBeansOfType(Class<T> type);
    // ... 其他枚举方法
}
// 4. 自动装配支持
public interface AutowireCapableBeanFactory extends BeanFactory {
    Object createBean(Class<?> beanClass);
    void autowireBean(Object existingBean);
    // ... 其他自动装配方法
}
// 5. 配置支持 (继承层次结构)
public interface ConfigurableBeanFactory 
    extends HierarchicalBeanFactory, SingletonBeanRegistry {
    void registerScope(String scopeName, Scope scope);
    void addBeanPostProcessor(BeanPostProcessor beanPostProcessor);
    // ... 其他配置方法
}
// 6. 完整配置支持 (组合所有能力)
public interface ConfigurableListableBeanFactory 
    extends ListableBeanFactory, AutowireCapableBeanFactory, ConfigurableBeanFactory {
    // 组合了枚举、自动装配和配置能力
}
// ==================== 实现类继承关系 ====================
// 1. 抽象骨架实现
public abstract class AbstractBeanFactory 
    extends FactoryBeanRegistrySupport 
    implements ConfigurableBeanFactory {
    // 实现BeanFactory基础逻辑
}
// 2. 自动装配能力实现  
public abstract class AbstractAutowireCapableBeanFactory 
    extends AbstractBeanFactory 
    implements AutowireCapableBeanFactory {
    // 实现自动装配和Bean创建
}
// 3. 默认完整实现
public class DefaultListableBeanFactory 
    extends AbstractAutowireCapableBeanFactory 
    implements ConfigurableListableBeanFactory, BeanDefinitionRegistry {
    // 完整功能实现
}
3.1.1.1BeanFactory根接口

Spring Framework对于组件的单一职责原则控制地非常好。BeanFactory的核心工作就是控制Bean在创建阶段的生命周期与bean对象的统一管理,而对于Bean从哪里来、如何被创建、有哪些依赖要被注入,都与BeanFactory无关,而是有包括BeanDefinitionReader在内的一些其他组件处理。

(1)作用域

产生单实例Bean和原型Bean所用的API是相同的,都是用@Scope注解来生命,然后用BeanFactory来创建。BeanFactory包含多个BeanDefinition的实现,每个bean对象的定义信息均由name进行唯一标识。根据bean对象的定义,SpringFramework中的工厂会返回所包含对象的独立实例原型模式(prototype),或者返回单个共享实例,即单实例模式(singleton)的替代方案。

(2)与环境配置的继承

BeanFactory本身是所有bean对象的注册中心,所有bean最终都在BeanFactory中创建和保存。另外BeanFactory中还集成了配置信息,它可以通过加载外部的properties文件,将配置文件的属性设置到bean对象中。

(3)Bean配置源

BeanFactory支持多种类型的Bean配置源。Bean定义的存储方式没有任何限制,可以是LDAP(轻型目录访问协议)、RDBMS(关系型数据库系统)、XML、properties文件等。BeanFactory的实现可以根据需要直接在Java代码中返回它创建的Java对象。

(4)层次性

与ListableBeanFactory中的方法相比,BeanFactory中的所有操作还将检查父级工厂(BeanFactory本身可以支持父子结构,这个父子结构的概念和实现由HierarchicalBeanFactory完成)。如果在BeanFactory势力中没有找到指定的Bean对象,则会在父工厂中搜索查找。BeabFactory实例中的Bean应该覆盖任何父工厂中的同名Bean。

(5)生命周期控制机制

BeanFactory中设有完整的生命周期控制机制,BeanFactory接口的内部实现了尽可能支持标准Bean的生命周期接口(Aware系列接口),用于初始化的Initializing接口、用于容器初始化完成后启动的Liifecycle接口等。

(6)拓展:IOC实现的两种权衡

在IOC实现上,推荐使用依赖注入(DI),尽可能避免依赖查找(DL)。依赖注入的思想是“推”,主张把组件所需的以来“推”到组件成员身上;以来查找的思想是“拉”,组件需要哪些以来需要组件自己去IOC容器中“拉取”。一般推荐通过“推”的方式,例如通过setter方法或者构造函数方法或者注解方法配置应用程序对象,而不是“拉”的方式,如借助BeanFactory进行依赖查找。

3.1.1.2HierarchicalBeanFactory

(1)HierarchicalBeanFactory的核心价值

HierarchicalBeanFactory 为 Spring 的 IoC 容器引入了父子层级关系,使得多个容器可以组织成一个层次结构,从而实现 Bean 定义的作用域隔离与继承。

public interface HierarchicalBeanFactory extends BeanFactory {
    
    // 1. 获取父容器
    // 如果当前容器没有父容器,则返回 null
    BeanFactory getParentBeanFactory();

    // 2. 判断当前【本地】容器是否包含指定名称的 Bean
    // 注意:这个方法【只查找当前容器】,不会委托给父容器查找
    boolean containsLocalBean(String name);
}

HierarchicalBeanFactory的核心价值在于:

容器层次结构:它允许一个 BeanFactory(子容器)有另一个 BeanFactory(父容器)。这是 Spring 中应用上下文(ApplicationContext)层次结构的基础。

作用域隔离与委托查找:子容器可以访问父容器中定义的 Bean(例如,在 Spring MVC 中,Web 层的 Controller 可以访问根容器中定义的 Service Bean)。父容器无法访问子容器中定义的 Bean(例如,根容器中的 Service 无法访问 Web 层的 Controller Bean)。这实现了很好的关注点分离。

覆盖 Bean 定义:子容器可以定义与父容器同名的 Bean,从而实现 Bean 的“覆盖”(通常用于测试或特定环境配置)。

(2)扩展:标准SpringBoot中的单容器与委托机制

如果说当前BeanFactory中有指定的Bean,父级BeanFactory中可能还有Bean吗?答案是可能会有,因为即便存在父子关系,它们在本质上也是不同的容器。因此有可能找到多个相同的Bean。换句话说,@Scope中声明的singleton只是在单独某一个容器中是单实例的,但有了层次性结构后,对于整体的多个容器就不是单实例的了。

而在标准的SpringBoot应用中,只有一个统一的Spring容器(ApplicationContext)来管理所有的Bean。也就是说,SpringBoot在默认情况下用的就是单容器,因此一般情况下singleton表明的就是单实例,而不用考虑多个容器。这与传统Spring Web项目中分离的父容器(业务层)和子容器(Web层)的复杂结构不同。

那么如果只有一个容器,“委托机制”在SpringBoot中还有用吗?对于“父子容器委托”,在单容器架构下,由于没有多个容器层级,这个机制自然不存在,也不再需要;对于“容器内单例委托”:这个机制依然有效且至关重要。例如,当使用@Configuration(proxyBeanMethods = true)时,SpringBoot会通过代理确保从配置类方法获取的Bean,始终是容器中唯一的单例。这可以看作是在单个容器内部,为了维护单例特性而进行的一种“委托检查”。

Spring Framework与SpringBoot管理Bean的容器简单对比如下:

3.1.1.3ListableBeanFactory

ListableBeanFactory 是一个能够枚举和批量查询 Bean 的工厂接口,它提供了按类型、按注解等多种方式来列出容器中的 Bean,而不仅仅是按名称查找单个 Bean。

public interface ListableBeanFactory extends BeanFactory {
    // 1. 检查容器是否包含指定名称的 Bean 定义(与 HierarchicalBeanFactory 的 containsLocalBean 不同,这个会考虑父容器?不一定,看实现)
    boolean containsBeanDefinition(String beanName);
    // 2. 获取容器中定义的 Bean 数量
    int getBeanDefinitionCount();
    // 3. 获取容器中所有定义的 Bean 的名称
    String[] getBeanDefinitionNames();
    // 4. 【核心方法】根据类型获取所有匹配的 Bean 名称
    String[] getBeanNamesForType(ResolvableType type);
    String[] getBeanNamesForType(Class<?> type);
    String[] getBeanNamesForType(Class<?> type, boolean includeNonSingletons, boolean allowEagerInit);
    // 5. 【最常用方法之一】根据类型获取所有匹配的 Bean 实例 Map(Bean 名 -> Bean 实例)
    <T> Map<String, T> getBeansOfType(Class<T> type) throws BeansException;
    <T> Map<String, T> getBeansOfType(Class<T> type, boolean includeNonSingletons, boolean allowEagerInit) throws BeansException;
    // 6. 【最常用方法之二】根据注解类型获取所有 Bean 的名称
    String[] getBeanNamesForAnnotation(Class<? extends Annotation> annotationType);
    // 7. 根据注解类型获取所有 Bean 的实例 Map(Bean 名 -> Bean 实例)
    Map<String, Object> getBeansWithAnnotation(Class<? extends Annotation> annotationType) throws BeansException;
    // 8. 在指定 Bean 上查找注解
    <A extends Annotation> A findAnnotationOnBean(String beanName, Class<A> annotationType) throws NoSuchBeanDefinitionException;
}

ListableBeanFactory 的核心价值在于:

批量枚举:能够获取容器中所有或某一类 Bean 的信息。

按类型查找:这是最常用的功能,可以获取实现某个接口或属于某个类的所有 Bean。

按注解查找:可以获取带有特定注解的所有 Bean。

Bean 定义查询:可以查询 Bean 的定义信息,而不仅仅是获取 Bean 实例。

关于选择性列举:ListableBeanFactory不是把当前容器中所有的Bean都列举出来,而是选择性的忽略手动注册(beanFactory.registerSingleton注册的)Bean,因为这个方法注册了一些仅供Spring Framework内部使用而不希望开发者直接操纵的Bean。

关于父容器:ListableBeanFactory 的方法默认只查找当前容器,不考虑父容器中的 Bean。这与 HierarchicalBeanFactory 的委托查找行为形成鲜明对比。如果你需要在整个层次结构中查找,通常需要使用工具类(如 BeanFactoryUtils)或在 ApplicationContext 层面操作。

关于延迟初始化:某些方法(如 getBeansOfType)有参数可以控制是否包括非单例 Bean 或是否允许提前初始化延迟加载的 Bean。

3.1.1.4AutowireCapaleBeanFactory

AutowireCapableBeanFactory 是一个能够自动装配 Bean 的工厂,它提供了多种自动装配模式,并允许在现有 Bean 实例上执行依赖注入,同时支持 Spring 容器外部的 Bean 的初始化和销毁回调。

public interface AutowireCapableBeanFactory extends BeanFactory {
    // 1. 创建一个新的 Bean 实例,并对其进行依赖注入和初始化回调
    Object createBean(Class<?> beanClass) throws BeansException;
    // 2. 对现有的 Bean 实例进行属性注入(依赖注入)
    void autowireBean(Object existingBean) throws BeansException;
    // 3. 配置一个现有的 Bean 实例,完成自动装配、应用 Bean 后置处理器等(包括初始化回调)
    Object configureBean(Object existingBean, String beanName) throws BeansException;
    // 4. 解析指定 Bean 的依赖项,并注入到 Bean 中
    Object resolveDependency(DependencyDescriptor descriptor, String requestingBeanName) throws BeansException;
    // 5. 应用 Bean 后置处理器(例如:初始化回调)
    Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName) throws BeansException;
    Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName) throws BeansException;
    // 6. 销毁指定的 Bean,执行销毁回调(如 @PreDestroy)
    void destroyBean(Object existingBean);
    // ... 其他方法
}

核心作用:

自动装配:支持按名称、按类型等自动装配模式。

Bean 生命周期管理:即使是在容器外部创建的 Bean 实例,也可以通过它来执行 Spring 的初始化回调和销毁回调。

集成其他框架:许多集成框架(如 Spring MVC、Quartz 集成等)使用它来管理非 Spring 管理的对象,使它们能够享受 Spring 的依赖注入和生命周期管理。

编程式 Bean 创建和装配:允许以编程方式创建 Bean,并对其进行依赖注入。

3.1.1.5ConfigurableBeanFactory

ConfigurableBeanFactory 是 Spring BeanFactory 的配置中心,它提供了大量的配置方法来定制 BeanFactory 的行为,是大多数可配置 BeanFactory 的父接口。

public interface ConfigurableBeanFactory extends HierarchicalBeanFactory, SingletonBeanRegistry { 
    // ==================== 基础容器配置 ====================
    /**
     * 设置父BeanFactory
     */
    void setParentBeanFactory(BeanFactory parentBeanFactory) throws IllegalStateException;
    /**
     * 设置Bean类加载器
     */
    void setBeanClassLoader(ClassLoader beanClassLoader);
    ClassLoader getBeanClassLoader();    
    /**
     * 设置临时类加载器(用于类型匹配等特殊场景)
     */
    void setTempClassLoader(ClassLoader tempClassLoader);
    ClassLoader getTempClassLoader();    
    /**
     * 设置是否缓存Bean元数据(默认为true,提高性能)
     */
    void setCacheBeanMetadata(boolean cacheBeanMetadata);
    boolean isCacheBeanMetadata();        
    // ==================== Bean生命周期配置 ====================    
    /**
     * 设置Bean定义名称生成器
     */
    void setBeanDefinitionDefaults(BeanDefinitionDefaults beanDefinitionDefaults);
    BeanDefinitionDefaults getBeanDefinitionDefaults();    
    /**
     * 管理当前正在创建中的Bean
     */
    void setCurrentlyInCreation(String beanName, boolean inCreation);
    boolean isCurrentlyInCreation(String beanName);       
    // ==================== 作用域管理 ====================    
    /**
     * 注册自定义作用域
     */
    void registerScope(String scopeName, Scope scope);   
    /**
     * 获取已注册的作用域名称
     */
    String[] getRegisteredScopeNames();
    
    /**
     * 获取指定的已注册作用域
     */
    Scope getRegisteredScope(String scopeName);     
    // ==================== 类型转换系统 ====================    
    /**
     * 设置类型转换服务
     */
    void setConversionService(ConversionService conversionService);
    ConversionService getConversionService();    
    /**
     * 添加属性编辑器注册器
     */
    void addPropertyEditorRegistrar(PropertyEditorRegistrar registrar);    
    /**
     * 注册自定义属性编辑器
     */
    void registerCustomEditor(Class<?> requiredType, Class<? extends PropertyEditor> propertyEditorClass);    
    /**
     * 初始化所有属性编辑器
     */
    void copyRegisteredEditorsTo(PropertyEditorRegistry registry);       
    // ==================== 表达式解析 ====================    
    /**
     * 设置Bean表达式解析器(用于SpEL表达式解析)
     */
    void setBeanExpressionResolver(BeanExpressionResolver resolver);
    BeanExpressionResolver getBeanExpressionResolver();        
    // ==================== 后置处理器管理 ====================    
    /**
     * 添加Bean后置处理器
     */
    void addBeanPostProcessor(BeanPostProcessor beanPostProcessor);  
    /**
     * 获取后置处理器数量
     */
    int getBeanPostProcessorCount();        
    // ==================== 嵌入式值解析 ====================   
    /**
     * 添加嵌入式值解析器(用于处理${...}占位符)
     */
    void addEmbeddedValueResolver(StringValueResolver valueResolver);    
    /**
     * 检查是否有嵌入式值解析器
     */
    boolean hasEmbeddedValueResolver();    
    /**
     * 解析嵌入式值(如${property.name})
     */
    String resolveEmbeddedValue(String value);        
    // ==================== Bean别名管理 ====================    
    /**
     * 注册Bean别名
     */
    void registerAlias(String beanName, String alias) throws BeanDefinitionStoreException;    
    /**
     * 解析所有别名目标
     */
    void resolveAliases(StringValueResolver valueResolver);      
    // ==================== 单例Bean管理 ====================   
    /**
     * 注册单例Bean
     */
    void registerSingleton(String beanName, Object singletonObject) throws IllegalStateException;   
    /**
     * 销毁单例Bean
     */
    void destroySingleton(String beanName);    
    /**
     * 销毁所有单例Bean
     */
    void destroySingletons();        
    // ==================== 其他配置 ====================  
    /**
     * 设置序列化ID(用于序列化目的)
     */
    void setSerializationId(String serializationId);  
    /**
     * 获取序列化ID
     */
    String getSerializationId();   
    /**
     * 获取合并的Bean定义
     */
    BeanDefinition getMergedBeanDefinition(String beanName) throws NoSuchBeanDefinitionException;  
    /**
     * 判断指定名称是否是FactoryBean
     */
    boolean isFactoryBean(String name) throws NoSuchBeanDefinitionException;
}

ConfigurableBeanFactory 的主要价值在于提供了对 BeanFactory 各个方面的细粒度控制:

Bean 生命周期配置:控制 Bean 的创建、初始化、销毁过程。

作用域管理:注册和管理自定义作用域。

类型转换系统:配置类型转换器和属性编辑器。

表达式解析:设置 SpEL 表达式解析器。

后置处理器管理:添加和管理 Bean 后置处理器。

类加载控制:设置类加载器和临时类加载器。

父子容器配置:设置父 BeanFactory。

3.1.1.6AbstractBeanFactory

一个抽象类,实现了BeanFactory接口的大部分功能,同时继承了HierarchicalBeanFactory以支持父子容器。它提供了配置BeanFactory的基本功能,比如父子容器的支持、Bean定义的获取、类型转换等。它还实现了SingletonBeanRegistry接口,用于管理单例Bean的生命周期。但是,它没有实现Bean定义的加载和解析,也没有实现创建Bean实例的具体逻辑,这些留给子类实现。

3.1.1.7AbstractAutowireCapableBeanFactory

继承自AbstractBeanFactory,并实现了AutowireCapableBeanFactory接口。它提供了完整的Bean创建、依赖注入和初始化的能力。具体来说,它实现了以下功能:

使用Bean定义中的信息来创建Bean实例(通过构造函数或工厂方法)。

进行依赖注入(按名称或按类型)。

处理Bean的生命周期回调(如InitializingBean和DisposableBean)。

应用BeanPostProcessor(在初始化前后进行自定义修改)。
这个类是Spring自动装配能力的核心实现。

3.1.1.8DefaultListableBeanFactory

继承自AbstractAutowireCapableBeanFactory,同时实现了ConfigurableListableBeanFactory和BeanDefinitionRegistry接口。它是Spring中功能最完整的BeanFactory实现,也是Spring容器(如ApplicationContext)内部使用的默认BeanFactory。它提供了以下关键功能:

注册和存储Bean定义(BeanDefinition)。

解析依赖关系(包括对@Autowired和@Value的支持)。

作为独立的IoC容器使用,也可以被配置为父子容器。

提供了ListableBeanFactory的功能,如枚举所有Bean名称、根据类型获取Bean等。

3.1.2ApplictionContext

ApplicationContext是Spring Framework的核心中央接口。在应用程序时,它是只读的,但是如果支持的话,它可以重新加载。ApplicationContext的核心功能大致包括访问Bean的能力、加载文件资源、事件发布、国际化支持、层级关系支持。其继承结构如下:

3.1.2.1ApplicationContext

注意,ApplicationContext的层级关系描述的是父子上下文,上下文中包含容器,但又不仅仅是容器。容器只负责管理Bean,但上下文中还包括动态增强、资源加载、事件监听机制等多方面扩展功能。

3.1.2.2ConfigurableApplicationContext

ConfigurableApplicationContext 是 Spring 容器的配置和控制中心,它继承自 ApplicationContext 接口并扩展了大量的配置和生命周期管理方法。如果说 ApplicationContext 是 Spring 提供给应用程序员使用的"成品容器",那么 ConfigurableApplicationContext 就是框架内部和需要深度定制的开发者所使用的"容器开发套件"。它在保留 ApplicationContext 所有高级功能(如国际化、事件发布、AOP 集成等)的基础上,额外提供了容器的配置能力(如设置父容器、环境属性、Bean 定义扫描路径)、生命周期控制(如刷新、启动、停止、关闭)以及底层组件的访问能力(如获取内部的 BeanFactory),从而实现了对 Spring 容器从静态配置到动态运行的全方位掌控。

3.1.2.3ApplicationContext的父接口

(1)EnvironmentCapable

在Spring Framework的底层源码中,如果一个接口的名称以Capable结尾,通常意味着可以通过这个接口的某个特定的方法(通常是getxxx())获取特定的组件。EnvironmentCapable接口与Environment强关联,Environment是Spring Framework中抽象出来的类似于运行环境的独立抽象,它内部存放着应用程序运行所需的一些配置。基于Spring Framework的项目在运行时包含两部分:应用程序本身和应用程序的运行时环境。

(2)MessageSource

MessageSouece是支持国际化的组件,ApplicationContext使用委托机制对国际化予以支持,在ApplicationContext实现类的内部整合了一个MessageSource的真正实现,以此完成国际化的支持。

(3)ApplicationEventPublisher

ApplicationEventPublisher是一个事件发布器。Spring Framework中,体现观察者模式的特性就是事件驱动和监听器。监听器充当订阅者,监听特定的事件;事件源充当被观察的主题,用来发布事件;IOC容器本身也是事件广播器,可以理解为观察者。Spring Framework的事件驱动核心可以划分为4部分:事件源、事件、广播器和监听器。

(4)ResourcePatternResolver

ResourcePatternResolver是资源模式解析器,会根据特定的路径解析资源文件。ResourcePatternResolver本身是ResourceLoader的扩展,它可以支持以Ant形式的带(*)号的路径解析。另外,ResourcePatterResolver本身是基于路径匹配的解析器,这种扩展实现的特点是可以根据特殊的路径返回多个匹配的资源路径。

/**
 * Spring Boot ApplicationContext的四个父接口演示
 * 展示从静态配置到动态运行的全方位掌控
 */
@SpringBootApplication
public class DemoApplication {
    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }
}
/**
 * 接口功能演示主类
 * 实现CommandLineRunner,在应用启动后运行演示代码
 */
@Component
class InterfaceDemo implements CommandLineRunner {    
    // 1. EnvironmentCapable - 通过ApplicationContext获取Environment
    @Autowired
    private ApplicationContext context;   
    // 2. MessageSource - 国际化支持组件
    @Autowired
    private MessageSource messageSource; 
    // 3. ApplicationEventPublisher - 事件发布器
    @Autowired
    private ApplicationEventPublisher eventPublisher;
    // 4. ResourcePatternResolver - 资源模式解析器
    @Autowired
    private ResourcePatternResolver resourceResolver;
    @Override
    public void run(String... args) throws Exception {
        System.out.println("=== Spring Boot ApplicationContext接口演示 ===");  
        // 演示1: EnvironmentCapable接口 - 环境配置管理
        demoEnvironmentCapable();
        // 演示2: MessageSource接口 - 国际化支持
        demoMessageSource();
        // 演示3: ApplicationEventPublisher接口 - 事件驱动
        demoEventPublisher();
        // 演示4: ResourcePatternResolver接口 - 资源解析
        demoResourceResolver();
    }
    /**
     * 演示1: EnvironmentCapable接口
     * 
     * ApplicationContext通过继承EnvironmentCapable接口,暴露getEnvironment()方法
     * 该方法返回Environment对象,代表应用程序的运行环境
     * 
     * 主要功能:
     * - 管理应用程序配置(application.properties/yml)
     * - 管理Profile(开发、测试、生产环境)
     * - 获取系统属性和环境变量
     */
    private void demoEnvironmentCapable() {
        System.out.println("\n1. EnvironmentCapable接口演示 - 环境配置管理:");
        // 通过ApplicationContext获取Environment对象
        // 这是EnvironmentCapable接口的核心方法
        Environment env = context.getEnvironment();
        // 获取应用程序配置
        String appName = env.getProperty("spring.application.name", "未配置");
        System.out.println("应用程序名称: " + appName);
        // 获取Profile信息
        String[] profiles = env.getActiveProfiles();
        System.out.println("激活的Profile: " + 
            (profiles.length == 0 ? "default" : String.join(",", profiles)));
        // 获取系统属性
        String javaVersion = env.getProperty("java.version");
        System.out.println("Java版本: " + javaVersion);
    }

    /**
     * 演示2: MessageSource接口
     * 
     * ApplicationContext通过委托机制整合MessageSource实现
     * 提供国际化消息支持,支持参数化消息和消息格式化
     * 
     * 核心机制:
     * 1. 消息键值对存储在资源文件中(messages.properties)
     * 2. 根据Locale选择不同的资源文件
     * 3. 支持消息参数替换
     */
    private void demoMessageSource() {
        System.out.println("\n2. MessageSource接口演示 - 国际化支持:");
        // 定义消息参数
        Object[] params = {"张三", 30};
        // 获取中文消息
        String zhMessage = messageSource.getMessage(
            "user.greeting", 
            params, 
            "你好, {0}!", // 默认消息
            Locale.CHINA
        );
        System.out.println("中文问候: " + zhMessage);
        // 获取英文消息
        String enMessage = messageSource.getMessage(
            "user.greeting", 
            params, 
            "Hello, {0}!", // 默认消息
            Locale.US
        );
        System.out.println("英文问候: " + enMessage);
        // MessageSource工作流程:
        // 1. 根据Locale查找对应的messages_xx.properties文件
        // 2. 查找user.greeting键对应的值
        // 3. 使用参数替换占位符{0}、{1}等
        // 4. 如果找不到则返回默认消息
    }

    /**
     * 演示3: ApplicationEventPublisher接口
     * 
     * 观察者模式在Spring中的实现
     * 包含四个核心组件:
     * 1. 事件源(Event Source)- 发布事件的对象
     * 2. 事件(Event)- 继承ApplicationEvent
     * 3. 监听器(Listener)- 使用@EventListener注解
     * 4. 广播器(Publisher)- ApplicationContext本身
     * 
     * 优势:解耦、异步处理、易于扩展
     */
    private void demoEventPublisher() {
        System.out.println("\n3. ApplicationEventPublisher接口演示 - 事件驱动:");
        // 发布用户登录事件
        UserLoginEvent loginEvent = new UserLoginEvent(this, "user001", "192.168.1.100");
        System.out.println("发布用户登录事件: " + loginEvent.getUsername());
        eventPublisher.publishEvent(loginEvent);
        // 发布订单创建事件
        OrderCreateEvent orderEvent = new OrderCreateEvent(this, "order001", 199.99);
        System.out.println("发布订单创建事件: " + orderEvent.getOrderId());
        eventPublisher.publishEvent(orderEvent);
        // 事件发布流程:
        // 1. 创建事件对象,包含事件源和数据
        // 2. 调用publishEvent()发布事件
        // 3. ApplicationContext广播事件给所有监听器
        // 4. 监听器处理事件(同步或异步)
    }

    /**
     * 演示4: ResourcePatternResolver接口
     * 
     * ResourceLoader的扩展,支持Ant风格路径匹配
     * 可以一次性获取多个匹配的资源
     * 
     * 特点:
     * - 支持classpath*:前缀,搜索所有jar包和类路径
     * - 支持Ant通配符:*(单个目录), **(多级目录)
     * - 返回多个Resource对象
     */
    private void demoResourceResolver() throws Exception {
        System.out.println("\n4. ResourcePatternResolver接口演示 - 资源解析:");
        
        // 使用Ant风格路径匹配所有配置文件
        // classpath*: 表示搜索所有类路径(包括jar包)
        // **/ 表示任意深度的子目录
        // *.properties 匹配所有properties文件
        Resource[] resources = resourceResolver.getResources(
            "classpath*:**/*.properties"
        );
        System.out.println("找到的配置文件数量: " + resources.length);
        for (Resource resource : resources) {
            System.out.println("  - " + resource.getFilename());
        }
        // 资源解析流程:
        // 1. 解析路径模式,支持Ant通配符
        // 2. 扫描所有类路径和jar包
        // 3. 匹配符合模式的文件路径
        // 4. 返回Resource对象数组
    }
}
/**
 * 自定义事件:用户登录事件
 * 继承ApplicationEvent,遵循Spring事件规范
 */
class UserLoginEvent extends ApplicationEvent {
    private final String userId;
    private final String username;
    private final String ipAddress;
    public UserLoginEvent(Object source, String userId, String ipAddress) {
        super(source);
        this.userId = userId;
        this.username = "用户" + userId; // 模拟用户名
        this.ipAddress = ipAddress;
    }
    public String getUserId() { return userId; }
    public String getUsername() { return username; }
    public String getIpAddress() { return ipAddress; }
}

/**
 * 自定义事件:订单创建事件
 * 展示不同类型的事件
 */
class OrderCreateEvent extends ApplicationEvent {
    private final String orderId;
    private final double amount;
    public OrderCreateEvent(Object source, String orderId, double amount) {
        super(source);
        this.orderId = orderId;
        this.amount = amount;
    }
    public String getOrderId() { return orderId; }
    public double getAmount() { return amount; }
}

/**
 * 事件监听器组件
 * 使用@EventListener注解标记监听方法
 * Spring会自动注册这些监听器
 */
@Component
class EventListeners {
    /**
     * 监听UserLoginEvent事件
     * 方法参数类型决定监听的事件类型
     */
    @EventListener
    public void handleUserLogin(UserLoginEvent event) {
        System.out.println("  [监听器] 用户登录: " + event.getUsername() + 
                          ", IP: " + event.getIpAddress());
        // 这里可以执行登录相关业务逻辑:
        // - 记录登录日志
        // - 更新最后登录时间
        // - 发送登录通知
    }
    /**
     * 监听OrderCreateEvent事件
     * 展示不同事件的监听
     */
    @EventListener
    public void handleOrderCreate(OrderCreateEvent event) {
        System.out.println("  [监听器] 订单创建: " + event.getOrderId() + 
                          ", 金额: ¥" + event.getAmount());
        // 这里可以执行订单相关业务逻辑:
        // - 库存扣减
        // - 发送订单通知
        // - 更新统计数据
    }
}
/**
 * 配置说明:
 * 
 * 1. 需要在resources目录下创建国际化文件:
 *    - messages.properties(默认)
 *    - messages_zh_CN.properties(中文)
 *    - messages_en_US.properties(英文)
 * 
 * 2. 文件内容示例:
 *    user.greeting=你好,{0}!欢迎回来!
 * 
 * 3. application.properties配置:
 *    spring.messages.basename=messages
 *    spring.application.name=接口演示应用
 */
/**
 * 源码设计模式总结:
 * 
 * 1. 委托模式:ApplicationContext将国际化功能委托给MessageSource
 * 2. 观察者模式:ApplicationEventPublisher实现事件发布-订阅
 * 3. 策略模式:ResourcePatternResolver提供不同的资源解析策略
 * 4. 适配器模式:Environment适配各种配置源(文件、环境变量等)
 */
3.1.2.4AbstractApplicationContext

简单来说,AbstractApplicationContext 是 Spring 容器的“核心引擎”,定义和实现了绝大部分应用上下文的特性和功能。与普通的BeanFactory相比,ApplicationContext能够检测在其内部bean对象中的特殊Bean,例如FactoryBeanProcesssors等。它加载资源文件的策略是直接继承自DefaultResourceLoader的策略,从类路径下加载;但在Web项目中加载策略可能发生改变,可以从ServletContext中加载等。它还通过模板方法设计模式,为所有不同类型的 Spring 容器(如基于 XML 的、基于注解的、Web 应用等)提供了一套标准的初始化和刷新流程。这个流程的核心就是它的 refresh() 方法。
每次启动或刷新 Spring 容器时,本质都是在调用 AbstractApplicationContext.refresh() 方法。这个方法定义了容器启动的完整生命周期,其核心步骤概括如下:
prepareRefresh(): 启动前的准备工作,如设置状态标志、初始化环境属性、准备早期事件集合。 
obtainFreshBeanFactory():创建或刷新底层 BeanFactory(真正的IoC容器),并加载所有Bean的定义(BeanDefinition)。 
prepareBeanFactory(): 对 BeanFactory 进行基本配置,如设置类加载器、注册内置的 BeanPostProcessor 等。 
postProcessBeanFactory():模板方法,留给子类扩展,用于对 BeanFactory进行后置处理(例如,Web环境会注册新的作用域)。 
invokeBeanFactoryPostProcessors():关键扩展点,执行所有 BeanFactoryPostProcessor,可以修改已加载的Bean定义(如处理 @Configuration)。 
registerBeanPostProcessors(): 注册所有 BeanPostProcessor(Bean后处理器),它们将在Bean实例化过程中介入,实现AOP、注解注入等功能。 
initMessageSource():初始化国际化(i18n)消息源组件,对应之前了解的 MessageSource 接口。 
initApplicationEventMulticaster():初始化事件发布器,对应 ApplicationEventPublisher 接口,为后续事件驱动做准备。 
onRefresh():模板方法,留给子类扩展,用于初始化特殊的Bean(例如Spring Boot在此处创建内嵌Web服务器)。 
registerListeners():注册所有事件监听器(ApplicationListener)。 
finishBeanFactoryInitialization():核心步骤,实例化所有非延迟加载的单例Bean,完成依赖注入,容器至此基本可用。 
finishRefresh():完成刷新,发布 ContextRefreshedEvent事件;初始化生命周期处理器,可选地触发 Lifecycle对Bean的启动。 

3.1.2.5GenericApplicationContext

GenericApplicationContext是注解驱动IOC容器的第一个非抽象实现类,是一个功能完备、现代化的通用应用上下文实现。简单说,它是预先配置好一个“即用型” BeanFactory 的、面向注解驱动的Spring容器。
GenericApplicationContext 的设计的核心理念在于组合优于继承。它不通过复杂的 refresh() 模板方法加载配置,而是内部持有一个 DefaultListableBeanFactory 实例作为其核心容器。注意,它并没有继承BeanFactory,而是组合了DefaultListableBeanFactory 。这个BeanFactoryGenericApplicationContext 的构造方法中已经初始化完毕,而初始化完毕的BeanFactory不允许在运行期间被重复刷新,在这里通过CAS算法来实现。在它的大部分方法(如 getBean)都是直接委托给这个内部 BeanFactory 去执行的。

基于以上源码,可以发现GenericApplicationContext为SpringBoot带来了两大优点。一是灵活的Bean定义注册。由于实现了 BeanDefinitionRegistry 接口,它允许你以编程方式、动态地注册Bean定义。这在集成测试、Spring Boot自动配置或框架集成时非常有用。二是无需调用 refresh() 即可注册。这是与 AbstractApplicationContext 传统子类(如 ClassPathXmlApplicationContext)的关键区别。可以在构建阶段注册所有Bean定义,然后在最后只调用一次 refresh() 来触发容器的初始化。它甚至可以通过 AnnotationConfigRegistry 接口支持注解扫描。

public class GenericApplicationContext extends AbstractApplicationContext implements BeanDefinitionRegistry {
    // 核心:持有一个现成的、可配置的BeanFactory
    private final DefaultListableBeanFactory beanFactory;
    // 构造函数直接初始化这个BeanFactory
    public GenericApplicationContext() {
        this.beanFactory = new DefaultListableBeanFactory();
    }
    // 几乎所有对Bean的操作,都委托给内部的beanFactory
    @Override
    public final ConfigurableListableBeanFactory getBeanFactory() {
        return this.beanFactory;
    }
    // 因为它实现了 BeanDefinitionRegistry 接口,
    // 所以可以直接、动态地注册Bean定义,而无需刷新整个上下文。
    @Override
    public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) {
        this.beanFactory.registerBeanDefinition(beanName, beanDefinition);
    }
}
3.1.2.6AnnotationConfigApplicationContext

完全基于Java注解配置的Spring IOC容器,在Spring 3.0中引入,继承自 GenericApplicationContext,标志着Spring从XML配置向注解配置的重要转变。内部同样持有一个 DefaultListableBeanFactory,但额外集成了 AnnotatedBeanDefinitionReader 和 ClassPathBeanDefinitionScanner,使其具备直接读取注解配置类并扫描包的能力。其核心功能是通过接收一个标注了 @Configuration 的配置类,或一个需要扫描的包路径,来启动容器。它会自动处理 @Bean、@Component 等注解,完成Bean的注册。

3.1.2.7AbstractRefreshableApplicationContext

一个支持容器刷新能力的抽象基类,是实现“可刷新”容器的模板。其核心在于重写了父类 AbstractApplicationContext 的 refreshBeanFactory() 方法。每次调用 refresh() 时,它会检查是否已存在 BeanFactory:如果存在,则销毁所有单例Bean并关闭原工厂;然后创建一个全新的 DefaultListableBeanFactory 实例,再通过抽象方法 loadBeanDefinitions() 加载新的Bean定义。这种“推倒重来”的刷新机制,特别适合需要在不重启应用的情况下重新加载外部配置(如修改XML文件后)的场景,为早期基于XML的Spring应用提供了灵活性。 ClassPathXmlApplicationContext 和 FileSystemXmlApplicationContext 都继承自它,并实现了 loadBeanDefinitions 方法,以从XML文件中加载配置。

这个类一般在传统的SpringFramework,SpringWebMvc+Mybatis等技术栈的项目中使用,而在SpringBoot中IOC容器全部都是基于注解驱动的,已经不再将XML配置文件作为配置源承载的搜选

3.1.3扩展:BeanFactory和ApplicationContext的对比

ApplicationContext 并不是 BeanFactory 的替代品,而是在其坚实内核之上构建的一个功能丰富的扩展。现代Spring应用开发中,几乎总是使用 ApplicationContext,直接使用 BeanFactory 的场景极少。Spring Boot的自动配置、Web MVC等功能都深度依赖 ApplicationContext 提供的扩展服务。 BeanFactory 的价值在于深入理解Spring容器的内核工作原理,或者在进行极端性能优化时。

3.2SpringBoot对IOC容器的扩展

SpringBoot并没有直接用Spring Framework现有的IOC容器,针对嵌入式Web容器的核心特性,扩展了更为强大的IOC容器。Spring Boot为嵌入式Web容器扩展了专门的IOC容器接口,其中WebServerApplicationContext是顶层接口,其下派生了适用于Servlet和响应式(Reactive)编程模型的两个主要实现。

// 1. WebServerApplicationContext - 顶层接口
// 位置:org.springframework.boot.web.context.WebServerApplicationContext
public interface WebServerApplicationContext extends ApplicationContext {
    /**
     * 获取当前应用上下文管理的嵌入式Web服务器实例(如Tomcat、Jetty、Netty)。
     * 这是Spring Boot“嵌入式”特性的核心方法。
     */
    WebServer getWebServer();

    /**
     * 获取此Web服务器所属的命名空间。
     * 常用于区分在同一应用程序中运行的多个服务器实例。
     */
    String getServerNamespace();
}
// 2. AnnotationConfigServletWebServerApplicationContext - Servlet实现类
// 位置:org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext
public class AnnotationConfigServletWebServerApplicationContext extends ServletWebServerApplicationContext
        implements AnnotationConfigRegistry {
    /**
     * 内部持有的注解配置Bean定义读取器。
     * 负责注册和处理 @Configuration、@Bean 等注解配置类[citation:4]。
     */
    private final AnnotatedBeanDefinitionReader reader;
    /**
     * 内部持有的类路径Bean定义扫描器。
     * 负责扫描指定包路径下的 @Component、@Service 等组件。
     */
    private final ClassPathBeanDefinitionScanner scanner;
    // 构造函数:初始化上述读取器和扫描器
    public AnnotationConfigServletWebServerApplicationContext() {
        this.reader = new AnnotatedBeanDefinitionReader(this);
        this.scanner = new ClassPathBeanDefinitionScanner(this);
    }
    /**
     * 核心方法:从父类继承并重写,在Spring容器刷新时被调用。
     * 其父类(ServletWebServerApplicationContext)在此方法中,
     * 通过工厂模式创建并初始化了内嵌的Servlet Web服务器(如Tomcat)[citation:2]。
     */
    @Override
    protected void onRefresh() {
        super.onRefresh(); // 触发Web服务器的创建
        // ... 其他初始化逻辑
    }
}
// 3. ReactiveWebServerApplicationContext - 响应式实现接口
// 位置:org.springframework.boot.web.reactive.context.ReactiveWebServerApplicationContext
// 注意:这是接口,具体实现是 AnnotationConfigReactiveWebServerApplicationContext[citation:2]
public interface ReactiveWebServerApplicationContext extends WebServerApplicationContext, ConfigurableApplicationContext {
    // 它继承了 WebServerApplicationContext,因此也拥有 getWebServer() 方法。
    // 这个接口标志了响应式容器的能力,其具体实现类负责创建Netty等响应式服务器。
}

AnnotationConfigServletWebServerApplicationContext和AnnotationConfigReactiveWebServerApplicationContext是Spring Boot启动时根据应用类型(WebApplicationType)动态创建的具体容器。它们都重写了AbstractApplicationContext.refresh()流程中的onRefresh()等方法,将嵌入式Web服务器的创建和启动无缝嵌入到了Spring容器的生命周期中。

简单来说,WebServerApplicationContext定义了嵌入式Web容器的基本契约。Spring Boot在此基础上,针对Servlet和响应式两种编程模型,分别提供了具体的、基于注解配置的实现类,从而实现了对IOC容器的扩展。

3.3选用注解驱动IOC容器的原因


基于以上差异,Spring Boot选择注解驱动主要有以下三个核心原因:

(1)与“约定优于配置”和“自动配置”理念无缝融合
Spring Boot的魔力在于自动配置。注解驱动是这一理念的最佳载体。自动配置类本身就是使用 @Configuration 和 @Bean 编写的,它们可以条件化地(通过 @ConditionalOnXxx 注解)注册Bean。

@Configuration
@ConditionalOnClass({DataSource.class, EmbeddedDatabaseType.class}) // 当类路径下存在这些类时才生效
public class DataSourceAutoConfiguration {
    @Bean
    @ConditionalOnMissingBean // 当用户未定义自己的DataSource时才生效
    public DataSource dataSource() {
        // 自动配置一个内嵌的H2数据库
        return new EmbeddedDatabaseBuilder().setType(EmbeddedDatabaseType.H2).build();
    }
}

这种“条件化Bean注册”模式用XML实现将异常繁琐,而注解使其变得优雅且强大。

(2)注解驱动完美契合了现代Java开发工作流

编译时检查:任何拼写错误或类型不匹配都会在编译期暴露,而不是等到应用启动失败。

IDE智能支持:可以轻松地“跳转到定义”(如跳转到 @Bean 方法的实现)或“查找用法”,极大地提升了开发和调试效率。

简化依赖注入:结合 @Autowired 或构造函数注入(Spring Boot推荐),使得Bean的依赖关系非常直观,易于测试(可直接通过构造函数注入模拟对象)。

(3)面向云原生和现代应用架构
注解驱动为以下场景提供了更灵活的支持:

环境特定配置:使用 @Profile(“prod”) 可以轻松地为生产环境配置不同的Bean。

配置动态绑定:与 @ConfigurationProperties 配合,可以将外部配置(application.yml)类型安全地绑定到Java Bean上,这是微服务配置中心化的基础。

编程式与声明式结合:在以AnnotationConfigServletWebServerApplicationContext为代表的容器中,你可以在Java配置里方便地以编程方式定制Web服务器端口、SSL等,这在容器化部署中至关重要。

3.4重要概念补充一:Environment

Environment 接口是Spring对环境配置的抽象,其核心是管理多个 PropertySource(属性源),并根据优先级获取属性。ConfigurableEnvironment 内部维护了一个 MutablePropertySources 对象,它持有一个 PropertySource<?> 的有序列表。当调用 getProperty() 时,会按顺序从高到低遍历列表,并返回第一个匹配的值。

public interface Environment extends PropertyResolver {
    String[] getActiveProfiles();
    boolean acceptsProfiles(String... profiles);
}
public interface ConfigurableEnvironment extends Environment, ConfigurablePropertyResolver {
    MutablePropertySources getPropertySources(); // 获取并操作属性源列表
    void merge(ConfigurableEnvironment parent);
}
// 属性源的抽象表示,例如 MapPropertySource 包装一个 Map
public abstract class PropertySource<T> {
    protected final String name;
    protected final T source;
    public abstract Object getProperty(String name);
}
// 可变的属性源列表,内部使用 CopyOnWriteArrayList
public class MutablePropertySources implements Iterable<PropertySource<?>> {
    private final List<PropertySource<?>> propertySourceList = new CopyOnWriteArrayList<>();
    public void addFirst(PropertySource<?> propertySource);
    public void addLast(PropertySource<?> propertySource);
    // ... 其他方法
}

在 SpringApplication.run() 的 prepareEnvironment() 方法中,Spring Boot会按特定顺序添加 PropertySource,例如系统属性、命令行参数,最后通过 EnvironmentPostProcessor 机制加载 application.properties/yml。这样确保了外部配置(如命令行)能覆盖内部配置。

3.4.1profile与property

Environment包含Profile与Property配置的信息,可以实现统一的配置存储和注入、配置属性的解析等行为。

Profile是基于环境的配置,可以裂解为一组Property的集合,用于区分不同的运行环境;而Property作为键值对形式的数据结构,是具体的配置项。

3.4.2Environment的结构设计

3.4.2.1PropertyResolver

Environment并非顶层接口,其继承了顶层接口是PropertyResolver。PropertyResolver是一个属性解析器,处理XML文件、注解配置类、普通Bean中用到的属性配置占位符。PropertyResolver使得nvironment具备获取属性配置元信息、以及解析展位符信息的能力。

public class PropertyResolverDemo {
    public static void main(String[] args) {
        // PropertyResolver 是顶层接口
        PropertyResolver resolver = new StandardEnvironment();
        // 1. 获取系统属性
        System.out.println(resolver.getProperty("java.version"));
        // 2. 解析占位符(最核心功能)
        String value = resolver.resolvePlaceholders("Java版本:${java.version}");
        System.out.println(value);
    }
}
3.4.2.2ConfigurableEnvironment

ConfigurableEnvironment直接继承自Environment和ConfigurablePropertyResolver,其特点是具备可配置的能力。

public class ConfigurableEnvironmentDemo {
    public static void main(String[] args) {
        ConfigurableEnvironment env = new StandardEnvironment();  
        // 可配置:激活指定 profile
        env.setActiveProfiles("dev", "test");
        // 获取激活的环境
        System.out.println("激活的Profile:" + String.join(",", env.getActiveProfiles()));
    }
}
3.4.2.3AbstractEnvironment

AbstractEnvironment继承自ConfigurableEnvironment。它会存储默认的profile,以及声明激活的所有profile,所有的propertySource也在这里存储。除此之外,还有一个很重要的成员PropertSourcePropertyResolver,只要是PropertyResolver下的工作,都委托给PropertSourcePropertyResolver完成。

public class AbstractEnvironmentDemo {
    public static void main(String[] args) {
        AbstractEnvironment env = new StandardEnvironment();  
        // 1. 存储并获取默认profile
        System.out.println("默认Profile:" + String.join(",", env.getDefaultProfiles()));
        // 2. 存储并获取所有属性源
        env.getPropertySources().forEach(ps -> {
            System.out.println("属性源:" + ps.getName());
        // 3. 真正解析工作委托给 PropertySourcePropertyResolver
        System.out.println("解析结果:" + env.resolvePlaceholders("用户:${user.name}"));
    }
}

3.5重要概念补充二:BeanDefinition

BeanDefinition 定义了创建一个Bean所需的所有元数据,包含Bean的类信息、属性、行为、依赖、配置信息等。它是Spring IOC容器的核心数据结构。

那么为什么需要 BeanDefinition 而不是直接使用 Bean呢?因为BeanDefinition能统一描述 Bean 的元信息,集中管理类全限定名、作用域、懒加载、初始化与销毁方法、依赖关系等配置;支持延迟实例化,容器启动时仅保存定义而不创建对象,避免启动慢与内存占用过高;同时让容器统一管理 Bean 的创建策略与作用范围,若直接创建 Bean 则会失去统一管控能力,无法实现 IOC 容器的核心特性。有了BeanDefinition,就可以按照约定的规则,任意解析生成Bean对象,也可以根据实际需求对解析和生成对象的过程任意扩展。

3.5.1BeanDefination的基本定义及实现

BeanDefination继承自AttributeAccessor、BeanMetadataElement接口,同一样AttributeAccessor具有配置Bean属性的功能,同BeanMetadataElement一样可以存放Bean的元信息。

AbstractBeanDefinition 是其BeanDefination的子类,作为BeanDefination的核心实现,包含了构建和配置Bean的完整信息。

public abstract class AbstractBeanDefinition extends BeanMetadataAttributeAccessor
        implements BeanDefinition, Cloneable {
    // --- Bean的“我是谁” ---
    private volatile Object beanClass; // Bean的类型(Class对象或字符串类名)
    private String scope = SCOPE_SINGLETON; // 作用域:单例(singleton)、原型(prototype)等
    // --- Bean的“如何造我” ---
    private boolean lazyInit = false; // 是否懒加载
    private String[] dependsOn; // 依赖的Bean名,确保先创建它们[citation:6]
    private boolean autowireCandidate = true; // 是否可作为自动装配候选者
    private int autowireMode = AUTOWIRE_NO; // 自动装配模式[citation:6]
    // --- Bean的“构造方法” ---
    private ConstructorArgumentValues constructorArgumentValues; // 构造器参数值[citation:6]
    private MutablePropertyValues propertyValues; // 属性值(用于Setter注入)
    // --- Bean的“从哪里来” ---
    // 三种实例化方式:1. Supplier; 2. 工厂方法; 3. 构造器(默认)[citation:6]
    private Supplier<?> instanceSupplier;
    private String factoryBeanName;
    private String factoryMethodName;
    // --- Bean的“初始化和销毁” ---
    private String initMethodName;
    private String destroyMethodName;
    // 验证方法
    public void validate() throws BeanDefinitionValidationException {
        // 例如,检查方法覆盖与工厂方法不能同时存在[citation:2]
        if (!getMethodOverrides().isEmpty() && getFactoryMethodName() != null) {
            throw new BeanDefinitionValidationException(...);
        }
    }
}

解析后的 BeanDefinition 会被注册到 BeanDefinitionRegistry(主要由 DefaultListableBeanFactory 实现,DefaultListableBeanFactory不仅是Bean对象的统一管理容器,而且是BeanDefinition的统一管理容器)中。 BeanDefinitionRegistry是维护BeanDefinition的注册中心,内部存放了IOC容器中Bean的定义信息,同时也是支撑其他组件和动态注册Bean的重要组件。其内部使用一个 ConcurrentHashMap 来存储,键是Bean名称,值是 BeanDefinition 对象。

public class DefaultListableBeanFactory extends ... implements BeanDefinitionRegistry {
    private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);
    private volatile List<String> beanDefinitionNames = new ArrayList<>(256);
    @Override
    public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) {
        // ... 校验、处理覆盖等逻辑[citation:2]
        this.beanDefinitionMap.put(beanName, beanDefinition);
        this.beanDefinitionNames.add(beanName);
        // ...
    }
}

AbstractBeanDefinition有三个具体的落地实现类,它们在 bean 定义的灵活性与使用场景上存在明显差异:GenericBeanDefinition 是最为通用的标准实现,不预设特定角色,支持父子 bean 定义的层级关系,可灵活适配各类常规 bean 配置场景;RootBeanDefinition 代表一份完整、最终定型的 bean 定义,不支持继承其他 bean 定义,通常用于合并后的 bean 定义或容器内部的最终实例化依据;ChildBeanDefinition 则专门用于继承并复用父 bean 定义的配置,自身无法独立使用,必须依赖父定义完成属性填充。三者共同构成了 Spring 容器对 bean 元信息从灵活定义、层级继承到最终固化的完整描述体系。

3.5.2BeanDefinition的使用示例

基于组件扫描的BeanDefinition

import org.springframework.stereotype.Component;
// 1. 用注解标记Bean
@Component
public class UserService {
}

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
// 2. 配置类:开启组件扫描
@Configuration
@ComponentScan("com.example")
public class AppConfig {
}

基于@Bean的BeanDefinition

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

// 配置类
@Configuration
public class AppConfig {

    // 手动声明Bean
    @Bean
    public UserService userService() {
        return new UserService();
    }
}

两者的区别如下:

对比维度基于组件扫描(@Component + @ComponentScan)基于 @Bean 注解
BeanDefinition 生成方式扫描包路径下带有 @Component 等注解的类,自动生成解析配置类中 @Bean 标记的方法,手动定义
灵活性较低,仅能对当前类进行声明,创建逻辑固定极高,可自定义实例化逻辑、构造参数、依赖注入
适用对象多用于项目自身编写的业务类多用于第三方库类、数据源、线程池等无法修改源码的类
控制粒度粗粒度,批量扫描注册细粒度,单个方法精确控制一个 Bean
依赖注入形式通常配合 @Autowired 自动注入可通过方法参数、代码逻辑手动控制依赖
代码侵入性需在类上添加注解,侵入较强无需修改类源码,无侵入性

3.6重要概念补充三:后置处理器

后置处理器是Spring框架最重要的扩展点,允许在容器和Bean生命周期的一些切入点处进行处理和干预。Spring Framework中的后置处理器主要有两种类型:针对BeanDefinition的后置处理器比如BeanFactoryPostProcessor,和针对Bean的后置处理器比如BeanPostProcessor。

3.6.1 BeanDefinitionRegistryPostProceser

BeanDefinitionRegistryPostProcessor 是 Spring 提供的顶级容器扩展接口,属于针对 BeanDefinition 的后置处理器,处理对象是 BeanDefinition 注册中心,执行时机极早,在所有 BeanDefinition注册完成之前、常规 BeanFactoryPostProcessor 执行之前触发;核心作用是手动向容器注册新的 BeanDefinition,也可对已有注册信息进行修改、移除,是 Spring 实现动态注册 Bean 的核心接口。

3.6.2 BeanFactoryPostProcessor

执行时机在所有 BeanDefinition 加载完成之后、Bean 实例化之前,主要用于修改或增强已注册的 BeanDefinition,是 Spring 实现外部配置加载、注解解析(如 @Configuration)的基石;它与 BeanDefinitionRegistryPostProcessor 的核心区别在于,后者侧重于向容器注册新的 BeanDefinition,而 BeanFactoryPostProcessor 侧重于对已注册完成的 BeanDefinition 进行修改与处理。

@FunctionalInterface
public interface BeanFactoryPostProcessor {
    void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;
}

ConfigurationClassPostProcessor 是处理 @Configuration、@ComponentScan 等注解的核心处理器。也可以自定义,例如动态修改属性。

public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
        BeanDefinition bd = beanFactory.getBeanDefinition("someBean");
        // 动态修改Bean的属性值
        MutablePropertyValues values = bd.getPropertyValues();
        values.add("username", "dynamicUser");
    }
}

3.6.3BeanPostProcessor

在Bean实例化、依赖注入之后,初始化方法(如 @PostConstruct、InitializingBean)调用前后执行。主要用于修改或包装Bean实例,AOP代理就是在这里创建的。

public interface BeanPostProcessor {
    // 初始化方法调用前执行
    @Nullable
    default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        return bean;
    }
    // 初始化方法调用后执行
    @Nullable
    default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        return bean;
    }
}

特殊子接口:还有功能更细分的处理器,如:InstantiationAwareBeanPostProcessor:干预对象的实例化动作,在Bean实例化之前和属性填充之前介入,拦截Bean对象的属性注入和自动装配。MergedBeanDefinitionPostProcessor:在Bean定义合并后、实例化前介入,常用于处理注解元数据,收集派生类的父类信息等。DestructionAwareBeanPostProcessor:当IOC容器关闭时,在ApplicationContext的close方法执行之前执行,比如监听器的引用释放和回调。

注册与执行顺序:后置处理器本身也是Bean。在 refresh() 的 registerBeanPostProcessors() 步骤中,Spring会从BeanFactory中找到所有 BeanPostProcessor 并按优先级注册(实现 PriorityOrdered -> Ordered -> 无顺序),这决定了它们的执行顺序

【注】:1.《SpringBoot源码解读与原理分析》LinkedBear著第三章阅读笔记,如果错误,欢迎指正

更多推荐