spring-beans 解析

Spring 框架中的 spring-beans 模块是 Spring IoC(控制反转)容器的核心组成部分,负责 Bean 的解析、定义、创建和管理。下面从解析的角度详细说明。

一、核心概念

1. Bean 定义解析的主要角色

  • BeanDefinition:Bean 的元数据描述(类名、作用域、生命周期、属性依赖等)

  • BeanDefinitionReader:读取配置(XML、注解、Java Config)并注册 BeanDefinition

  • BeanDefinitionRegistry:BeanDefinition 的注册中心(通常是 DefaultListableBeanFactory)

  • BeanFactoryPostProcessor:允许在 Bean 实例化前修改 BeanDefinition

二、XML 配置解析流程

典型配置

XML 复制代码
<beans xmlns="http://www.springframework.org/schema/beans">
    <bean id="userService" class="com.example.UserService">
        <property name="userDao" ref="userDao"/>
    </bean>
</beans>

解析步骤

  1. 资源加载ResourceLoader 加载 XML 资源

  2. 文档解析XmlBeanDefinitionReader 使用 DOM/SAX 解析 XML

  3. Bean 注册 :解析 <bean> 元素生成 GenericBeanDefinition,注册到 BeanDefinitionRegistry

关键代码位置

java 复制代码
// XmlBeanDefinitionReader 核心方法
public int loadBeanDefinitions(Resource resource) {
    // 1. 获取 XML 的 Document 对象
    Document doc = this.documentLoader.loadDocument(...);
    // 2. 注册 Bean 定义
    return registerBeanDefinitions(doc, resource);
}

// DefaultBeanDefinitionDocumentReader
protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
    // 遍历 <beans> 下的子元素
    if (delegate.isDefaultNamespace(root)) {
        for (Element ele : root.getChildNodes()) {
            if (ele.getNodeName().equals("bean")) {
                processBeanDefinition(ele, delegate);
            }
        }
    }
}

三、注解配置解析流程

常用注解

  • @Component, @Service, @Repository, @Controller

  • @Autowired, @Value, @Qualifier

解析方式

java 复制代码
// 方式1:使用 AnnotationConfigApplicationContext
new AnnotationConfigApplicationContext(AppConfig.class);

// 方式2:组件扫描
@ComponentScan(basePackages = "com.example")
public class AppConfig { }

// 解析核心类
// ClassPathBeanDefinitionScanner
// AnnotatedBeanDefinitionReader

内部处理

java 复制代码
// ClassPathBeanDefinitionScanner 扫描包
public int scan(String... basePackages) {
    // 1. 查找候选 Bean(根据 @Component 元注解)
    Set<BeanDefinition> candidates = findCandidateComponents(basePackage);
    // 2. 注册 BeanDefinition(解析 @Scope, @Lazy 等)
    for (BeanDefinition candidate : candidates) {
        registerBeanDefinition(candidate);
    }
}

四、BeanDefinition 合并解析

当存在父子 <bean> 定义时:

java 复制代码
<bean id="parent" abstract="true">
    <property name="commonProp" value="common"/>
</bean>
<bean id="child" parent="parent" class="com.example.Child">
    <property name="childProp" value="child"/>
</bean>

Spring 会调用 getMergedBeanDefinition() 将父子定义合并 成一个完整的 RootBeanDefinition

五、解析过程中的扩展点

1. BeanFactoryPostProcessor

java 复制代码
@Component
public class CustomBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
        BeanDefinition bd = beanFactory.getBeanDefinition("userService");
        bd.setScope("prototype"); // 修改作用域
    }
}

2. BeanDefinitionRegistryPostProcessor

优先于普通 BeanFactoryPostProcessor,可注册新的 BeanDefinition。

3. 自定义 XML 标签解析

java 复制代码
// 实现 NamespaceHandler 和 BeanDefinitionParser
// 在 META-INF/spring.handlers 中注册

六、流程图总结

bash 复制代码
配置文件 (XML/注解/JavaConfig)
         ↓
BeanDefinitionReader 加载
         ↓
解析生成 BeanDefinition (元数据)
         ↓
注册到 BeanDefinitionRegistry
         ↓
BeanFactoryPostProcessor 处理 (修改 BeanDefinition)
         ↓
完成解析,容器持有 BeanDefinition 集合
         ↓
后续用于 Bean 实例化 (getBean 时或预实例化)

七、关键类总结

类名 职责
BeanDefinition 存储 Bean 的元信息
BeanDefinitionReader 从配置源读取并注册 BeanDefinition
BeanDefinitionRegistry 管理 BeanDefinition 的容器
BeanDefinitionParserDelegate 解析 XML 中的 <bean> 元素
ClassPathBeanDefinitionScanner 扫描类路径下的注解 Bean
ConfigurationClassPostProcessor 核心注解配置解析器(处理 @Configuration, @Bean 等)

spring-beans 的解析本质:将配置声明 转换为内存中的 BeanDefinition 对象,为后续的依赖注入和生命周期管理做好准备。理解解析过程有助于掌握 Spring 容器启动的全貌,以及在需要时自定义 Bean 的加载行为。

相关推荐
华如锦9 分钟前
面了很多 Java转AI Agent方向,一些面试题总结
java·开发语言·人工智能·python·ai
睡不醒男孩03082311 分钟前
CLup 6.x 版本中针对StarRocks 存算一体集群的完整操作手册
java·服务器·网络·clup
程序员黑豆1 小时前
Java中怎么实现字符串拼接呢【AI全栈开发】
java
fox_lht1 小时前
15.3.改进我们之前的输入、输出项目
开发语言·后端·学习·rust
大鸡腿同学2 小时前
用 AI 肝了一个星期的智能客服助手,看看怎么个事
后端
IT_陈寒2 小时前
Python的os.path.join居然能这么坑?
前端·人工智能·后端
java1234_小锋2 小时前
LangChain4j 开发Java Agent智能体- 多模态支持
java·开发语言·langchain4j
艳阳天_.2 小时前
星瀚弹框页面实现
java·前端·python
张忠琳2 小时前
【Go 1.26.4】Golang Channel 深度解析
开发语言·后端·golang