当前位置: 首页 > news >正文

Spring 源码解读(二)——BeanDefinition

Spring 源码解读(二)——BeanDefinition

image-20250223183309171

核心原则

  • 不要深究:理解即可,细节不必深究。
  • 基本准则
    • 接口:定义能力。
    • 抽象类:定义可复用、可重用的代码。

BeanDefinition 继承关系

BeanDefinition 继承关系


BeanDefinition 的作用

翻译自源码文档
BeanDefinition 描述了一个 Bean 实例,包含属性值、构造函数参数值以及由具体实现提供的更多信息。

BeanDefinition 示例


核心点解析

  1. 最终转换为 RootDefinition
    例如,GenericBeanDefinition(Spring 2.5 引入)是通过 XML 配置读取的,最终会转换为 RootBeanDefinition

  2. 抽象类 AbstractBeanDefinition
    其中定义了通用的成员变量,子类会继承这些变量。

    AbstractBeanDefinition 示例

  3. RootBeanDefinition 的特殊性
    RootBeanDefinition 中,getParent() 方法返回 null


代码测试

以下是一个简单的测试代码,演示如何创建和配置 GenericBeanDefinition

@Test
public void test() throws IntrospectionException {
    // 创建 GenericBeanDefinition
    GenericBeanDefinition beanDefinition = new GenericBeanDefinition();
    beanDefinition.setBeanClassName("com.lucifer.User");
    beanDefinition.setLazyInit(false);

    // 设置属性值
    MutablePropertyValues propertyValues = new MutablePropertyValues();
    propertyValues.add("name", "lucifer");
    propertyValues.add("age", 18);

    beanDefinition.setPropertyValues(propertyValues);
    System.out.println(beanDefinition);
}

从xml中获取bean的过程

1. 整体流程概述

从 XML 中获取 Bean 的过程可以分为以下几个步骤:

  1. 加载 XML 配置文件:读取 XML 文件并解析为 Document 对象。
  2. 解析 Bean 定义:将 XML 中的 <bean> 标签解析为 BeanDefinition
  3. 注册 Bean 定义:将 BeanDefinition 注册到 BeanFactory 中。
  4. 实例化 Bean:根据 BeanDefinition 创建 Bean 实例。
  5. 依赖注入:为 Bean 注入所需的依赖。

2. 源码解析

2.1 加载 XML 配置文件

Spring 通过 XmlBeanDefinitionReader 类加载 XML 配置文件,并将其解析为 Document 对象。

// XmlBeanDefinitionReader.java
public int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException {
    return loadBeanDefinitions(new EncodedResource(resource));
}
  • Resource:表示 XML 文件的资源对象。
  • EncodedResource:对资源进行编码处理。
2.2 解析 Bean 定义

Spring 使用 DefaultBeanDefinitionDocumentReader 解析 XML 文件中的 <bean> 标签。

// DefaultBeanDefinitionDocumentReader.java
protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
    if (delegate.isDefaultNamespace(root)) {
        NodeList nl = root.getChildNodes();
        for (int i = 0; i < nl.getLength(); i++) {
            Node node = nl.item(i);
            if (node instanceof Element) {
                Element ele = (Element) node;
                if (delegate.isDefaultNamespace(ele)) {
                    parseDefaultElement(ele, delegate); // 解析默认元素(如 <bean>)
                } else {
                    delegate.parseCustomElement(ele); // 解析自定义元素
                }
            }
        }
    } else {
        delegate.parseCustomElement(root); // 解析自定义元素
    }
}
  • parseDefaultElement:解析 <bean> 标签。
  • parseCustomElement:解析自定义标签(如 <context:component-scan>)。
2.3 注册 Bean 定义

解析后的 BeanDefinition 会被注册到 DefaultListableBeanFactory 中。

// DefaultListableBeanFactory.java
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
        throws BeanDefinitionStoreException {
    this.beanDefinitionMap.put(beanName, beanDefinition);
    this.beanDefinitionNames.add(beanName);
}
  • beanDefinitionMap:存储 Bean 名称与 BeanDefinition 的映射。
  • beanDefinitionNames:存储所有 Bean 的名称。
2.4 实例化 Bean

Spring 通过 AbstractBeanFactorygetBean 方法实例化 Bean。

// AbstractBeanFactory.java
public Object getBean(String name) throws BeansException {
    return doGetBean(name, null, null, false);
}
  • doGetBean:核心方法,负责 Bean 的实例化和依赖注入。
2.5 依赖注入

Spring 通过 AbstractAutowireCapableBeanFactory 完成依赖注入。

// AbstractAutowireCapableBeanFactory.java
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
    // 注入属性值
    if (mbd.getPropertyValues() != null) {
        applyPropertyValues(beanName, mbd, bw, mbd.getPropertyValues());
    }
}
  • applyPropertyValues:将属性值注入到 Bean 中。

3. 代码示例

以下是一个简单的 XML 配置文件示例:

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="user" class="com.example.User">
        <property name="name" value="John"/>
        <property name="age" value="30"/>
    </bean>
</beans>

运行 HTML

3.1 加载 XML 配置文件
ClassPathResource resource = new ClassPathResource("applicationContext.xml");
XmlBeanFactory beanFactory = new XmlBeanFactory(resource);
3.2 获取 Bean 实例
User user = (User) beanFactory.getBean("user");
System.out.println(user.getName()); // 输出: John
System.out.println(user.getAge());  // 输出: 30

4. 关键类解析

类名作用
XmlBeanDefinitionReader读取 XML 配置文件并解析为 BeanDefinition
DefaultBeanDefinitionDocumentReader解析 XML 文件中的 <bean> 标签。
DefaultListableBeanFactory存储和管理 BeanDefinition
AbstractBeanFactory提供 getBean 方法,负责 Bean 的实例化和依赖注入。
AbstractAutowireCapableBeanFactory实现 Bean 的依赖注入逻辑。

5. 总结

从 XML 中获取 Bean 的过程可以分为以下几个步骤:

  1. 加载 XML 配置文件:通过 XmlBeanDefinitionReader 读取 XML 文件。
  2. 解析 Bean 定义:将 <bean> 标签解析为 BeanDefinition
  3. 注册 Bean 定义:将 BeanDefinition 注册到 BeanFactory 中。
  4. 实例化 Bean:通过 getBean 方法创建 Bean 实例。
  5. 依赖注入:将属性值注入到 Bean 中。

相关文章:

  • 基于 go-wrk 在 Windows 环境下对 Go Web 应用进行 HTTP 压力测试
  • 选与不选?从暴力枚举到背包dp
  • 第13篇:Vue Router基础使用
  • 旋转位置编码(ROPE)详解:从Transformer到现代前沿
  • 管道-过滤器、隐式调用、解释器架构风格对比
  • Spring——SpringSecurity开发经验实战
  • 给小米/红米手机root(工具基本为官方工具)——KernelSU篇
  • 【Python量化金融实战】-第1章:Python量化金融概述:1.1量化金融的定义与发展历程
  • QListView实现文件选择功能
  • JAVAEE一>Spring IoC和DI详解
  • 2024全国青少年信息素养大赛python复赛真题--装错信封
  • 【自学嵌入式(9)ESP8266网络服务器的使用】
  • spring中关于Bean的复习(IOC和DI)
  • 深度学习(5)-卷积神经网络
  • Qt 是一个跨平台的 C++ 应用程序框架
  • 如何了解和学习“未知的未知”
  • python安装教程,最新版本Python3.12安装教程(附安装包)
  • 计算机组成与接口5
  • 爬虫基础之爬取某基金网站+数据分析
  • 相机标定(张正友标定法)
  • 临安区建设局网站/推广拉新app哪几个靠谱
  • 官方网站建设必要性/游戏推广对接平台
  • 白领兼职做网站/线上培训课程
  • 网站制作公司挣钱吗/外链发布论坛
  • 网站开发培训多少钱/网络销售面试问题有哪些
  • 西安网站建设 企业建站/凤凰网台湾资讯