深度解析 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);}
}

两周年 ~ 一起努力叭

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/659878.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

记录浏览器打开网站拦截提示不安全解决方法

浏览器可能会因为多种原因显示“不安全”的警告,这通常是由于安全设置不当或配置错误造成的。以下是一些常见的原因和解决方法: 1. HTTPS未启用 原因:如果网站使用HTTP而不是HTTPS,浏览器可能会显示不安全的警告。 解决方法:配置SSL/TLS证书并使用HTTPS来加密数据传输…

深度解析:人工智能作画算法的原理与技术

引言 在数字艺术的探索中&#xff0c;人工智能&#xff08;AI&#xff09;作画算法以其独特的创造性和艺术性引起了广泛的兴趣。这些算法不仅仅是简单的图像处理工具&#xff0c;它们背后蕴藏着复杂的神经网络和深度学习模型。本文将深入探讨AI作画算法的原理与技术&#xff0…

CSS的布局模式

前言&#xff1a; 我们可以看到京东的官网上的一些例子&#xff08;如下图&#xff09;&#xff0c;在同一排中能够存在多个div&#xff0c;这是通过布局方式&#xff08;例如浮动&#xff09;来实现的。 CSS传统的布局模式&#xff1a; <1>普通流&#xff08;又称之为标…

Linux学习笔记:进程间的通信.共享内存shm

共享内存shm 什么是共享内存shm共享内存的特点关键函数ftokshmgetshmatshmdtshmctl 代码示例 什么是共享内存shm 进程间通信的前提:必须让不同的进程看到同一份资源,并且这个资源是OS提供的 而共享内存(Share memory)就是在内核共享内存区找一块物理内存空间,并允许多个进程共…

ReentrantReadWriteLock(可重入读写锁)源码解读与使用

&#x1f3f7;️个人主页&#xff1a;牵着猫散步的鼠鼠 &#x1f3f7;️系列专栏&#xff1a;Java源码解读-专栏 &#x1f3f7;️个人学习笔记&#xff0c;若有缺误&#xff0c;欢迎评论区指正 目录 1. 前言 2. 读写锁是什么 3. ReentrantReadWriteLock是什么 4. 源码解…

公文写作笔记

标题 最后一行的日期&#xff0c;后边占4个格子。两个数字占一格。落款单位在日期的正上方。 格式积累 内容&#xff1a; ①开头&#xff1a;缘由 ②主题&#xff1a;对策&#xff08;别人做得好&#xff0c;就借鉴&#xff09; ③结尾&#xff1a;简单的总结&#xff08;字…

聊聊Mysql的两阶段提交

从图中可看出&#xff0c;事务的提交过程有两个阶段&#xff0c;就是将 redo log 的写入拆成了两个步骤&#xff1a;prepare 和 commit&#xff0c;中间再穿插写入bin log&#xff0c;具体如下&#xff1a; prepare 阶段&#xff1a;将 事务的修改写入到 redo log&#xff0c;同…

GitLab(史上最全GitLab安装使用文章!!!)

GitLab 是一个基于网络的Git仓库管理工具&#xff0c;是开源的。基本每个公司都会有属于自己公司内部的GitLab 官方网站&#xff1a;https://about.gitlab.com/ GitLab文档&#xff1a;https://docs.gitlab.cn/jh/install/requirements.html 安装 所需配置 这里采用Cento…

TMS320F280049 EQEP模块--QWDOG UTIME(4)

QWDOG功能框图 下图是watchdog的功能框图。在WDE使能后&#xff0c;16bit宽的计数器QWDTMR在64分频的时钟下开始计数&#xff0c;在QCLK时会被重置。当QWDTMR到达QWDPRD时会置位WTO并产生WDTOUT事件。 所以该watchdog是用来检测电机是否转动的。假设电机停止转动&#xff0c;则…

stm32 hid自定义接收发送程序开发过程记录

cubleMX配置如下 修改端点描述符一次传输的数据大小 根据cubelMX标准在这里修改 编译错误 直接修改&#xff08;因为没有使用nodef &#xff09;编译通过 修改报告描述符&#xff08;默认的描述符无法传输数据&#xff09; 参考&#xff1a;USB协议详解第10讲&#xff08;USB描…

CUDA CPP Unity Compute Shader Linear Algebra

为学 开始一个新的学习计划&#xff0c;涵盖&#xff1a; 主题学习内容CUDAProfessional CUDA C Programming/NVIDIA CUDA初级教程视频(周斌)CCPrimer / The Cherno CPPUnity Compute ShaderUdemy Learn to Write Unity Compute ShadersLinear AlgebraMIT 18.06 Prof.Gilbert…

【RabbitMQ】可靠性策略(幂等,消息持久化)

MQ可靠性策略 发送者的可靠性问题生产者的重连生产者确认 MQ的可靠性数据持久化Lazy Queue 消费者的可靠性问题消费者确认机制消息失败处理 业务幂等性简答问题 发送者的可靠性问题 生产者的重连 可能存在由于网络波动&#xff0c;出现的客户端连接MQ失败&#xff0c;我们可以…