Spring 的容器 API 有三个不同层次:Bean 元数据、根据元数据创建对象的工厂,以及将工厂与应用程序服务协调起来的应用程序上下文。保持这些层次分离,可以更容易地理解 Spring 源代码和扩展点。
Bean 定义和注册表 #
BeanDefinition 是一个 Bean 的可变元数据。它记录 Bean 类或类名、作用域、构造函数参数、属性值、限定符、工厂方法、生命周期方法、角色、源位置和显式依赖。父子元数据关系独立于 Java 继承。
常见实现服务于不同的注册路径:
RootBeanDefinition表示 Bean 工厂使用的合并定义。ChildBeanDefinition从命名的父定义继承元数据。GenericBeanDefinition可以在合并前表达独立或派生自父定义的元数据。AnnotatedGenericBeanDefinition公开已注册类的注解元数据。ScannedGenericBeanDefinition公开类路径扫描期间读取的元数据,而无需先加载组件类。
BeanDefinitionRegistry 按 Bean 名称存储定义。其核心操作是注册、移除和查询定义;DefaultListableBeanFactory 和 GenericApplicationContext 是重要实现。
AnnotatedBeanDefinitionReader 注册显式提供的组件类:
var context = new GenericApplicationContext();
var reader = new AnnotatedBeanDefinitionReader(context);
reader.register(OrderService.class);
context.refresh();ClassPathBeanDefinitionScanner 搜索候选组件的包并注册其定义。两种机制都会应用注解作用域、命名、限定符、条件和 BeanDefinitionCustomizer 回调。定制器可以在注册期间进行有针对性的元数据更改,而无需实现注册表后处理器。
BeanFactory、FactoryBean 和 ObjectFactory
#
BeanFactory 是运行时注册表和依赖解析 API。它定位定义、创建 Bean、解析协作者、管理单例身份并应用生命周期处理器。ListableBeanFactory 增加枚举功能,HierarchicalBeanFactory 增加父级查找,ConfigurableListableBeanFactory 向框架基础设施公开容器配置。应用程序代码应依赖领域协作者,而不是将 getBean() 作为服务定位器调用。
三个名称相似的类型具有不同职责:
BeanFactory是容器。FactoryBean<T>是创建另一个对象的 Bean。查找其名称会返回产品;在名称前加&会返回工厂本身。getObjectType()和isSingleton()描述产品。ObjectFactory<T>是带有getObject()的最小回调。Spring 使用它进行延迟获取和内部创建回调。ObjectProvider<T>扩展了该模型,提供可选、有序和基于流的访问。
应用程序上下文层次结构 #
ApplicationContext 扩展 ListableBeanFactory、HierarchicalBeanFactory、MessageSource、ApplicationEventPublisher、ResourcePatternResolver 和相关环境能力。ConfigurableApplicationContext 增加 refresh()、close()、环境配置以及访问可配置工厂等生命周期操作。
AbstractApplicationContext 实现刷新算法。专用基类决定定义如何到达工厂:
GenericApplicationContext拥有一个内部DefaultListableBeanFactory。可以在一次refresh()调用前通过其注册表 API 注册定义。AnnotationConfigApplicationContext将通用上下文与AnnotatedBeanDefinitionReader和ClassPathBeanDefinitionScanner结合。其构造函数可以注册类或扫描包,然后刷新。- 支持 Servlet 的上下文增加 Web 作用域和 Servlet 资源,但保留相同的核心工厂契约。
某些较旧的上下文实现会在刷新期间重新创建 Bean 工厂,而 GenericApplicationContext 不支持重复刷新尝试。框架扩展必须遵循具体上下文的生命周期,而不是假设每个上下文都可以刷新多次。
刷新和生成的定义 #
注解注册最初会为提供的类创建定义。在刷新期间,ConfigurationClassPostProcessor 解析 @Configuration、组件扫描、导入和 @Bean 方法,然后在实例化普通 Bean 之前注册其他定义。注册表后处理器可以在同一阶段生成更多定义。Spring 的 AOT 处理可以提前生成注册代码,但生成的定义仍然进入相同的 Bean 工厂模型。
ApplicationStartup 会对启动进行检测,但不改变生命周期语义。DefaultApplicationStartup 是低开销的空操作实现,BufferingApplicationStartup 保留有界步骤数据,FlightRecorderApplicationStartup 发出 Java Flight Recorder 事件。StartupStep 具有名称、标签和明确的结束;自定义基础设施应保持标签成本低廉,因为启动检测运行在关键路径上。
选择扩展点 #
使用与需求匹配的最窄层次:
- 使用
BeanDefinitionCustomizer在注册时定制定义。 - 使用
BeanDefinitionRegistryPostProcessor或BeanFactoryPostProcessor添加或转换元数据。 - 使用
BeanPostProcessor拦截实例。 - 使用
FactoryBean构建产生对象的 Bean。 - 在
GenericApplicationContext或应用程序上下文子类型上构建完整的协调容器。
评论
在 GitHub 上阅读或评论(发表评论需要登录)