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

在这里插入图片描述

一、BeanDefinition 的概述

1.1 BeanDefinition 的定位

核心组件的介绍

  1. BeanFactory(Bean 工厂):BeanFactory 是 Spring 框架的核心接口,负责管理应用中的 Bean 实例。它是 Spring IoC 容器的基础,提供了一种配置机制来管理 Bean 的生命周期和依赖关系。
  2. ApplicationContext(应用上下文):ApplicationContext 是 BeanFactory 的子接口,它扩展了 BeanFactory 的功能,提供了更多的企业级特性,例如国际化、事件传播、资源加载等。ApplicationContext 是 Spring 中最常用的 IoC 容器,负责加载配置文件、管理 Bean 实例并提供各种服务。
  3. BeanDefinition(Bean 定义):BeanDefinition 定义了 Bean 的配置元数据,包括类名、依赖关系、初始化方法、销毁方法等。BeanFactory 使用 BeanDefinition 来创建 Bean 实例。
  4. FactoryBean:FactoryBean 是一个特殊的 Bean,它实现了 FactoryBean 接口,并且负责返回其他 Bean 的实例。FactoryBean 允许开发者在创建 Bean 实例的过程中进行一些定制化的操作,例如延迟加载、按需初始化等。
  5. Bean:Bean 是 Spring 管理的对象实例,它们是应用程序的核心组件,通过 Spring IoC 容器来管理和配置。

组件之间的关系

在这里插入图片描述

1.2 BeanDefition 的作用

  1. 定义 Bean 的配置元数据:BeanDefinition 定义了每个 Bean 的配置信息,包括类名、依赖关系、初始化方法、销毁方法等。它描述了如何创建和配置一个特定的 Bean 实例。
  2. 实例化 Bean:BeanDefinition 充当了实例化 Bean 的指南。Spring IoC 容器根据 BeanDefinition 中的配置信息来创建 Bean 实例,并在需要时将其初始化。
  3. 管理 Bean 的生命周期:BeanDefinition 中定义了 Bean 的生命周期方法,如初始化方法和销毁方法,Spring IoC 容器负责调用这些方法,以确保 Bean 在适当的时候进行初始化和销毁。
  4. 处理 Bean 的依赖关系:BeanDefinition 中包含了 Bean 之间的依赖关系,Spring IoC 容器使用这些信息来解析和管理 Bean 之间的依赖关系,确保它们在合适的时间被注入和初始化。
  5. 支持各种配置方式:BeanDefinition 支持多种配置方式,包括 XML 配置、注解配置和 Java 配置。它为开发者提供了灵活的选择,可以根据项目的需求和个人喜好选择合适的配置方式。

二、BeanDefinition 源码解读

由于方法过多,仅仅展示方法分析,想要深入了解的读者可以自行结合源码解读分析,这里不做过多描述。

2.1 BeanDefinition 接口的主要方法

在这里插入图片描述

主要方法

  • getBeanClassName():获取Bean的类名。
  • setBeanClassName(String beanClassName):设置Bean的类名。
  • getFactoryMethodName():获取工厂方法的名字(如果Bean是通过工厂方法创建的)。
  • setFactoryMethodName(String factoryMethodName):设置工厂方法的名字。
  • getScope():获取Bean的作用域。
  • setScope(String scope):设置Bean的作用域。
  • isSingleton():检查Bean是否是单例。
  • isPrototype():检查Bean是否是原型。
  • isLazyInit():检查Bean是否延迟初始化。
  • getPropertyValues():获取Bean的属性值。
  • getConstructorArgumentValues():获取构造函数参数值。
  • getDependsOn():获取Bean依赖的其他Bean的名称。
  • getAutowireCandidate():获取是否是自动装配候选者。
  • getDescription():获取Bean的描述。
  • getResourceDescription():获取资源描述。
  • getRole():获取Bean的角色。

2.2 BeanDefinition 的实现类

BeanDefinition 的作用是描述一个 Bean 的元数据信息,包括其类名、作用域、依赖关系等。通过 BeanDefinition,Spring 容器可以了解每个 Bean 的配置信息,从而进行实例化、依赖注入等操作。

2.2.1 实现类的区别

Bean定义 的关键类区别

  1. RootBeanDefinition
    • RootBeanDefinitionAbstractBeanDefinition 的直接子类。
    • 通常用于定义独立的 Bean,即非继承关系的 Bean。
    • 可以通过 setBeanClass(Class beanClass) 方法设置 Bean 的类型,通过 setConstructorArgumentValues(ConstructorArgumentValues constructorArgumentValues) 设置构造函数参数值,以及通过其他方法设置 Bean 的属性、作用域、依赖关系等。
  2. ChildBeanDefinition
    • ChildBeanDefinition 也是 AbstractBeanDefinition 的直接子类。
    • 用于定义继承关系中的子 Bean,即通过 标签的 parent 属性来继承父 Bean 的配置信息的子 Bean。
    • RootBeanDefinition 相比,ChildBeanDefinition 可以继承父 Bean 的属性配置,并可以覆盖或添加新的属性。
    • 通常不直接实例化 ChildBeanDefinition,而是通过 XML 配置文件或者 Java 代码中的父子 Bean 定义来间接使用。
  3. AbstractBeanDefinition
    • AbstractBeanDefinition 是一个抽象类,用于表示 Bean 的抽象定义,定义了 Bean 的基本属性和行为 。
    • 它定义了 Bean 的基本属性和行为,包括类、作用域、构造函数参数、属性值、初始化方法、销毁方法等。
    • RootBeanDefinitionChildBeanDefinition 都是 AbstractBeanDefinition 的子类,因此它们继承了 AbstractBeanDefinition 中定义的一些属性和方法,如 setBeanClass()setScope() 等。

仅仅展示抽象类AbstractBeanDefinition的定义Bean的主要行为。想要了解子类RootBeanDefinition和子类ChildBeanDefinition,以及其它定义的Bean行为的读者,可自行查看相应的源码,进行解读。

2.2.2 setBeanClassName()

在这里插入图片描述

2.2.3 getDependsOn()

在这里插入图片描述

2.2.4 setScope()

在这里插入图片描述

2.3 BeanDefinition 运用的设计模式

最突出的设计模式包括:

  1. 模板方法模式
    • AbstractBeanDefinition 定义了一个模板方法 validate(),该方法规定了 Bean 定义的验证流程,但是具体的验证细节交由子类实现。这符合模板方法模式的思想,即定义一个算法的骨架,将具体步骤的实现延迟到子类中。
  2. 工厂方法模式
    • AbstractBeanDefinition 是一个抽象类,其中包含一个抽象的工厂方法 getBeanClass(),用于获取 Bean 的类对象。具体的 Bean 类型由子类提供,符合工厂方法模式的定义,即将对象的创建延迟到子类中。
  3. 策略模式
    • AbstractBeanDefinition 中的属性 scopelazyInit 等代表了不同的策略,决定了 Bean 的作用域和是否延迟初始化。这些属性的值可以根据具体情况动态地设置,从而改变 Bean 的行为,符合策略模式的思想,即定义一系列算法,将它们封装起来,并且使它们可以相互替换。
  4. 装饰器模式
    • Spring 中的 Bean 定义可能会有各种各样的装饰器(例如:属性装饰器、生命周期装饰器等),用于增强或修改 Bean 的行为。AbstractBeanDefinition 可以作为装饰器的基类,通过组合的方式实现装饰器模式,为 Bean 定义提供灵活的扩展机制。
  5. 建造者模式
    • 在 Spring 中,通过 BeanDefinitionBuilder 类来构建 AbstractBeanDefinition 实例,它使用了建造者模式,通过一系列的方法链式调用来设置 AbstractBeanDefinition 的属性,并最终构建出一个完整的 Bean 定义对象。

2.4 BeanDefinition 的注册和解析过程

BeanDefinition 的注册过程通常由 BeanDefinitionRegistry 接口及其实现类(如 DefaultListableBeanFactory)负责。

2.4.1 BeanDefinitionRegistry接口

在这里插入图片描述

2.4.2 DefaultListableBeanFactory实现类

查看 DefaultListableBeanFactory 类的 registerBeanDefinition() 方法,该方法用于向容器注册 BeanDefinition。其它方法读者感兴趣,可自行查看源码。

在这里插入图片描述

三、实际案例分析

通过一个简单的健身房会员管理系统来演示如何在日常开发中使用BeanDefinition。

需求:

  1. 每个会员都有一个唯一的会员编号、姓名和注册日期。
  2. 系统需要能够添加新会员、查询会员信息和删除会员。
  1. 会员类:Member
public class Member {
    private int memberId;
    private String name;
    private LocalDate registrationDate;

    // 省略构造函数、getter和setter方法
}
  1. 会员管理服务类:MemberManagementService
import java.util.HashMap;
import java.util.Map;

public class MemberManagementServiceImpl {
    private Map<Integer, Member> members = new HashMap<>();
    private int nextMemberId = 1;

    /**
     * 添加新会员
     */
    public void addMember(String name) {
        Member member = new Member();
        member.setMemberId(nextMemberId++);
        member.setName(name);
        member.setRegistrationDate(LocalDate.now());
        members.put(member.getMemberId(), member);
    }

    /**
     * 查询会员信息
     */
    public Member getMember(int memberId) {
        return members.get(memberId);
    }

    /**
     * 删除会员
     */
    public void removeMember(int memberId) {
        members.remove(memberId);
    }
}
  1. Spring配置类:AppConfig
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * 使用了BeanDefinition来声明了 MemberManagementService 的 Bean
 */
@Configuration
public class AppConfig {

    @Bean
    public MemberManagementService memberManagementService() {
        return new MemberManagementService();
    }
}
  1. 应用程序入口类:Main
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class Main {
    public static void main(String[] args) {
        ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
        MemberManagementService memberManagementService = context.getBean(MemberManagementService.class);

        // 添加会员
        memberManagementService.addMember("Alice");
        memberManagementService.addMember("Bob");

        // 查询会员信息并显示
        Member member1 = memberManagementService.getMember(1);
        System.out.println("Member 1: " + member1.getName());

        Member member2 = memberManagementService.getMember(2);
        System.out.println("Member 2: " + member2.getName());

        // 删除会员
        memberManagementService.removeMember(1);
    }
}

两周年 ~ 一起努力叭

  • 135
    点赞
  • 112
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 226
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 226
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

忆~遂愿

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值