深度解析 Spring 源码:从 BeanDefinition 源码探索 Bean 的本质

本文涉及的产品
云解析 DNS,旗舰版 1个月
全局流量管理 GTM,标准版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
简介: 深度解析 Spring 源码:从 BeanDefinition 源码探索 Bean 的本质

深度解析 Spring 源码:从 BeanDefinition 源码探索 Bean 的本质

 

Spring 的核心之一是对 Bean 的管理,而 `BeanDefinition` 是 Spring 中定义和描述 Bean 信息的关键接口。通过深入了解 `BeanDefinition` 及其相关实现类,我们可以更好地理解 Spring 容器如何管理 Bean 的生命周期和依赖注入过程。

 

1. BeanDefinition 的概述

 

`BeanDefinition` 是 Spring 框架中一个重要的接口,它定义了 Bean 的所有属性,包括:

 

- Bean 的类名

- 作用域(如单例或原型)

- 初始化方法和销毁方法

- 构造函数参数

- 属性值

 

`BeanDefinition` 是 Spring IOC 容器用来描述 Bean 元数据的基本单位。

 

2. BeanDefinition 的层次结构

 

`BeanDefinition` 接口有多个子接口和实现类,主要包括:

 

- **RootBeanDefinition**: 代表一个标准的、可实例化的 Bean 定义。

- **ChildBeanDefinition**: 代表一个 Bean 定义,它从父定义中继承配置。

- **GenericBeanDefinition**: 一个通用的 Bean 定义实现,通常用于通过编程方式注册 Bean。

- **AbstractBeanDefinition**: 提供了 `BeanDefinition` 接口的基础实现,是多个具体实现类的父类。

 

3. BeanDefinition 接口源码

 

以下是 `BeanDefinition` 接口的简化版源码:

 

```java
public interface BeanDefinition extends AttributeAccessor, BeanMetadataElement {
 
    // 常量定义,如 SCOPE_SINGLETON 和 SCOPE_PROTOTYPE
    String SCOPE_SINGLETON = ConfigurableBeanFactory.SCOPE_SINGLETON;
    String SCOPE_PROTOTYPE = ConfigurableBeanFactory.SCOPE_PROTOTYPE;
 
    // 获取和设置 Bean 的类名
    @Nullable
    String getBeanClassName();
    void setBeanClassName(@Nullable String beanClassName);
 
    // 获取和设置 Bean 的作用域
    @Nullable
    String getScope();
    void setScope(@Nullable String scope);
 
    // 判断是否为单例或原型
    boolean isSingleton();
    boolean isPrototype();
 
    // 获取和设置初始化方法和销毁方法
    @Nullable
    String getInitMethodName();
    void setInitMethodName(@Nullable String initMethodName);
 
    @Nullable
    String getDestroyMethodName();
    void setDestroyMethodName(@Nullable String destroyMethodName);
 
    // 获取和设置构造函数参数和值
    ConstructorArgumentValues getConstructorArgumentValues();
    MutablePropertyValues getPropertyValues();
 
    // 克隆当前 BeanDefinition 对象
    BeanDefinition cloneBeanDefinition();
}
```

 

4. AbstractBeanDefinition 类

 

`AbstractBeanDefinition` 是 `BeanDefinition` 接口的抽象实现,提供了大部分通用属性的存储和操作方法。以下是 `AbstractBeanDefinition` 类的一些关键代码:

 

```java
public abstract class AbstractBeanDefinition implements BeanDefinition, Cloneable {
 
    @Nullable
    private volatile Object beanClass;
 
    @Nullable
    private String scope = SCOPE_DEFAULT;
 
    private boolean singleton = true;
    private boolean prototype = false;
 
    @Nullable
    private String initMethodName;
 
    @Nullable
    private String destroyMethodName;
 
    private ConstructorArgumentValues constructorArgumentValues;
 
    private MutablePropertyValues propertyValues;
 
    protected AbstractBeanDefinition() {
        this(null, null);
    }
 
    protected AbstractBeanDefinition(@Nullable ConstructorArgumentValues cargs,
                                     @Nullable MutablePropertyValues pvs) {
        this.constructorArgumentValues = (cargs != null ? cargs : new ConstructorArgumentValues());
        this.propertyValues = (pvs != null ? pvs : new MutablePropertyValues());
    }
 
    @Override
    @Nullable
    public String getBeanClassName() {
        Object beanClassObject = this.beanClass;
        return (beanClassObject instanceof Class ? ((Class<?>) beanClassObject).getName() : (String) beanClassObject);
    }
 
    @Override
    public void setBeanClassName(@Nullable String beanClassName) {
        this.beanClass = beanClassName;
    }
 
    @Override
    @Nullable
    public String getScope() {
        return this.scope;
    }
 
    @Override
    public void setScope(@Nullable String scope) {
        this.scope = scope;
        this.singleton = SCOPE_SINGLETON.equals(scope) || SCOPE_DEFAULT.equals(scope);
        this.prototype = SCOPE_PROTOTYPE.equals(scope);
    }
 
    @Override
    public boolean isSingleton() {
        return this.singleton;
    }
 
    @Override
    public boolean isPrototype() {
        return this.prototype;
    }
 
    @Override
    @Nullable
    public String getInitMethodName() {
        return this.initMethodName;
    }
 
    @Override
    public void setInitMethodName(@Nullable String initMethodName) {
        this.initMethodName = initMethodName;
    }
 
    @Override
    @Nullable
    public String getDestroyMethodName() {
        return this.destroyMethodName;
    }
 
    @Override
    public void setDestroyMethodName(@Nullable String destroyMethodName) {
        this.destroyMethodName = destroyMethodName;
    }
 
    @Override
    public ConstructorArgumentValues getConstructorArgumentValues() {
        return this.constructorArgumentValues;
    }
 
    @Override
    public MutablePropertyValues getPropertyValues() {
        return this.propertyValues;
    }
 
    @Override
    public AbstractBeanDefinition cloneBeanDefinition() {
        try {
            return (AbstractBeanDefinition) super.clone();
        } catch (CloneNotSupportedException ex) {
            throw new IllegalStateException("Should never happen", ex);
        }
    }
}
```

 

5. 解析 BeanDefinition 的使用

 

`BeanDefinition` 通常通过 XML 配置文件、注解配置或编程方式进行注册。在 Spring 启动过程中,这些 `BeanDefinition` 会被解析并注册到 `BeanFactory` 中。

 

5.1 通过 XML 配置注册 BeanDefinition

 

在 XML 配置文件中定义 Bean 时,Spring 会使用 `XmlBeanDefinitionReader` 来解析 XML 文件并生成相应的 `BeanDefinition` 对象。

 

```xml
<bean id="exampleBean" class="com.example.MyClass" scope="singleton">
    <property name="name" value="example"/>
</bean>
```

 

5.2 通过注解配置注册 BeanDefinition

 

使用注解时,Spring 会通过 `ClassPathBeanDefinitionScanner` 扫描类路径下的注解并生成 `BeanDefinition`。

 

```java
@Component
public class ExampleBean {
    // ...
}
```

 

5.3 通过编程方式注册 BeanDefinition

 

可以通过编程方式手动创建和注册 `BeanDefinition`。

 

```java
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
GenericBeanDefinition beanDefinition = new GenericBeanDefinition();
beanDefinition.setBeanClass(MyClass.class);
beanDefinition.setScope(BeanDefinition.SCOPE_SINGLETON);
context.registerBeanDefinition("myBean", beanDefinition);
context.refresh();
```

 

6. 总结

 

通过深入了解 `BeanDefinition` 及其相关实现类,我们可以看到 Spring 是如何描述和管理 Bean 的元数据的。`BeanDefinition` 的设计使得 Spring 容器能够以统一的方式处理不同来源的 Bean 定义,不论是 XML 配置、注解还是编程方式。这种灵活性和统一性是 Spring 框架强大和广受欢迎的重要原因之一。通过分析这些源码,我们可以更好地理解 Spring 的工作原理,并在实际开发中更有效地使用和扩展 Spring 框架。

目录
相关文章
|
3天前
|
Java 测试技术 Windows
咦!Spring容器里为什么没有我需要的Bean?
【10月更文挑战第11天】项目经理给小菜分配了一个紧急需求,小菜迅速搭建了一个SpringBoot项目并完成了开发。然而,启动测试时发现接口404,原因是控制器包不在默认扫描路径下。通过配置`@ComponentScan`的`basePackages`字段,解决了问题。总结:`@SpringBootApplication`默认只扫描当前包下的组件,需要扫描其他包时需配置`@ComponentScan`。
|
4天前
|
JavaScript Java 关系型数据库
自主版权的Java诊所管理系统源码,采用Vue 2、Spring Boot等技术栈,支持二次开发
这是一个自主版权的Java诊所管理系统源码,支持二次开发。采用Vue 2、Spring Boot等技术栈,涵盖患者管理、医生管理、门诊管理、药店管理、药品管理、收费管理、医保管理、报表统计及病历电子化等功能模块。
|
8天前
|
存储
让星星⭐月亮告诉你,HashMap的put方法源码解析及其中两种会触发扩容的场景(足够详尽,有问题欢迎指正~)
`HashMap`的`put`方法通过调用`putVal`实现,主要涉及两个场景下的扩容操作:1. 初始化时,链表数组的初始容量设为16,阈值设为12;2. 当存储的元素个数超过阈值时,链表数组的容量和阈值均翻倍。`putVal`方法处理键值对的插入,包括链表和红黑树的转换,确保高效的数据存取。
29 5
|
10天前
|
Java Spring
Spring底层架构源码解析(三)
Spring底层架构源码解析(三)
|
10天前
|
XML Java 数据格式
Spring底层架构源码解析(二)
Spring底层架构源码解析(二)
|
5天前
|
XML Java 数据格式
Spring IOC容器的深度解析及实战应用
【10月更文挑战第14天】在软件工程中,随着系统规模的扩大,对象间的依赖关系变得越来越复杂,这导致了系统的高耦合度,增加了开发和维护的难度。为解决这一问题,Michael Mattson在1996年提出了IOC(Inversion of Control,控制反转)理论,旨在降低对象间的耦合度,提高系统的灵活性和可维护性。Spring框架正是基于这一理论,通过IOC容器实现了对象间的依赖注入和生命周期管理。
15 0
|
10天前
|
缓存 Java 程序员
Map - LinkedHashSet&Map源码解析
Map - LinkedHashSet&Map源码解析
26 0
|
10天前
|
算法 Java 容器
Map - HashSet & HashMap 源码解析
Map - HashSet & HashMap 源码解析
24 0
|
10天前
|
存储 Java C++
Collection-PriorityQueue源码解析
Collection-PriorityQueue源码解析
20 0
|
10天前
|
安全 Java 程序员
Collection-Stack&Queue源码解析
Collection-Stack&Queue源码解析
24 0

推荐镜像

更多