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

2024-04-30 20:44

本文主要是介绍深度解析 Spring 源码:从BeanDefinition源码探索Bean的本质,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

在这里插入图片描述

文章目录

    • 一、BeanDefinition 的概述
      • 1.1 BeanDefinition 的定位
      • 1.2 BeanDefition 的作用
    • 二、BeanDefinition 源码解读
      • 2.1 BeanDefinition 接口的主要方法
      • 2.2 BeanDefinition 的实现类
        • 2.2.1 实现类的区别
        • 2.2.2 setBeanClassName()
        • 2.2.3 getDependsOn()
        • 2.2.4 setScope()
      • 2.3 BeanDefinition 运用的设计模式
      • 2.4 BeanDefinition 的注册和解析过程
        • 2.4.1 BeanDefinitionRegistry接口
        • 2.4.2 DefaultListableBeanFactory实现类
    • 三、实际案例分析

一、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 {@Beanpublic 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);}
}

两周年 ~ 一起努力叭

这篇关于深度解析 Spring 源码:从BeanDefinition源码探索Bean的本质的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/949875

相关文章

JSON字符串转成java的Map对象详细步骤

《JSON字符串转成java的Map对象详细步骤》:本文主要介绍如何将JSON字符串转换为Java对象的步骤,包括定义Element类、使用Jackson库解析JSON和添加依赖,文中通过代码介绍... 目录步骤 1: 定义 Element 类步骤 2: 使用 Jackson 库解析 jsON步骤 3: 添

Java中注解与元数据示例详解

《Java中注解与元数据示例详解》Java注解和元数据是编程中重要的概念,用于描述程序元素的属性和用途,:本文主要介绍Java中注解与元数据的相关资料,文中通过代码介绍的非常详细,需要的朋友可以参... 目录一、引言二、元数据的概念2.1 定义2.2 作用三、Java 注解的基础3.1 注解的定义3.2 内

Java中使用Java Mail实现邮件服务功能示例

《Java中使用JavaMail实现邮件服务功能示例》:本文主要介绍Java中使用JavaMail实现邮件服务功能的相关资料,文章还提供了一个发送邮件的示例代码,包括创建参数类、邮件类和执行结... 目录前言一、历史背景二编程、pom依赖三、API说明(一)Session (会话)(二)Message编程客

Java中List转Map的几种具体实现方式和特点

《Java中List转Map的几种具体实现方式和特点》:本文主要介绍几种常用的List转Map的方式,包括使用for循环遍历、Java8StreamAPI、ApacheCommonsCollect... 目录前言1、使用for循环遍历:2、Java8 Stream API:3、Apache Commons

JavaScript中的isTrusted属性及其应用场景详解

《JavaScript中的isTrusted属性及其应用场景详解》在现代Web开发中,JavaScript是构建交互式应用的核心语言,随着前端技术的不断发展,开发者需要处理越来越多的复杂场景,例如事件... 目录引言一、问题背景二、isTrusted 属性的来源与作用1. isTrusted 的定义2. 为

Java循环创建对象内存溢出的解决方法

《Java循环创建对象内存溢出的解决方法》在Java中,如果在循环中不当地创建大量对象而不及时释放内存,很容易导致内存溢出(OutOfMemoryError),所以本文给大家介绍了Java循环创建对象... 目录问题1. 解决方案2. 示例代码2.1 原始版本(可能导致内存溢出)2.2 修改后的版本问题在

Java CompletableFuture如何实现超时功能

《JavaCompletableFuture如何实现超时功能》:本文主要介绍实现超时功能的基本思路以及CompletableFuture(之后简称CF)是如何通过代码实现超时功能的,需要的... 目录基本思路CompletableFuture 的实现1. 基本实现流程2. 静态条件分析3. 内存泄露 bug

Java中Object类的常用方法小结

《Java中Object类的常用方法小结》JavaObject类是所有类的父类,位于java.lang包中,本文为大家整理了一些Object类的常用方法,感兴趣的小伙伴可以跟随小编一起学习一下... 目录1. public boolean equals(Object obj)2. public int ha

Go中sync.Once源码的深度讲解

《Go中sync.Once源码的深度讲解》sync.Once是Go语言标准库中的一个同步原语,用于确保某个操作只执行一次,本文将从源码出发为大家详细介绍一下sync.Once的具体使用,x希望对大家有... 目录概念简单示例源码解读总结概念sync.Once是Go语言标准库中的一个同步原语,用于确保某个操

SpringBoot项目中Maven剔除无用Jar引用的最佳实践

《SpringBoot项目中Maven剔除无用Jar引用的最佳实践》在SpringBoot项目开发中,Maven是最常用的构建工具之一,通过Maven,我们可以轻松地管理项目所需的依赖,而,... 目录1、引言2、Maven 依赖管理的基础概念2.1 什么是 Maven 依赖2.2 Maven 的依赖传递机