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

相关文章

Java编译生成多个.class文件的原理和作用

《Java编译生成多个.class文件的原理和作用》作为一名经验丰富的开发者,在Java项目中执行编译后,可能会发现一个.java源文件有时会产生多个.class文件,从技术实现层面详细剖析这一现象... 目录一、内部类机制与.class文件生成成员内部类(常规内部类)局部内部类(方法内部类)匿名内部类二、

SpringBoot实现数据库读写分离的3种方法小结

《SpringBoot实现数据库读写分离的3种方法小结》为了提高系统的读写性能和可用性,读写分离是一种经典的数据库架构模式,在SpringBoot应用中,有多种方式可以实现数据库读写分离,本文将介绍三... 目录一、数据库读写分离概述二、方案一:基于AbstractRoutingDataSource实现动态

使用Jackson进行JSON生成与解析的新手指南

《使用Jackson进行JSON生成与解析的新手指南》这篇文章主要为大家详细介绍了如何使用Jackson进行JSON生成与解析处理,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录1. 核心依赖2. 基础用法2.1 对象转 jsON(序列化)2.2 JSON 转对象(反序列化)3.

Springboot @Autowired和@Resource的区别解析

《Springboot@Autowired和@Resource的区别解析》@Resource是JDK提供的注解,只是Spring在实现上提供了这个注解的功能支持,本文给大家介绍Springboot@... 目录【一】定义【1】@Autowired【2】@Resource【二】区别【1】包含的属性不同【2】@

springboot循环依赖问题案例代码及解决办法

《springboot循环依赖问题案例代码及解决办法》在SpringBoot中,如果两个或多个Bean之间存在循环依赖(即BeanA依赖BeanB,而BeanB又依赖BeanA),会导致Spring的... 目录1. 什么是循环依赖?2. 循环依赖的场景案例3. 解决循环依赖的常见方法方法 1:使用 @La

Java枚举类实现Key-Value映射的多种实现方式

《Java枚举类实现Key-Value映射的多种实现方式》在Java开发中,枚举(Enum)是一种特殊的类,本文将详细介绍Java枚举类实现key-value映射的多种方式,有需要的小伙伴可以根据需要... 目录前言一、基础实现方式1.1 为枚举添加属性和构造方法二、http://www.cppcns.co

Elasticsearch 在 Java 中的使用教程

《Elasticsearch在Java中的使用教程》Elasticsearch是一个分布式搜索和分析引擎,基于ApacheLucene构建,能够实现实时数据的存储、搜索、和分析,它广泛应用于全文... 目录1. Elasticsearch 简介2. 环境准备2.1 安装 Elasticsearch2.2 J

Java中的String.valueOf()和toString()方法区别小结

《Java中的String.valueOf()和toString()方法区别小结》字符串操作是开发者日常编程任务中不可或缺的一部分,转换为字符串是一种常见需求,其中最常见的就是String.value... 目录String.valueOf()方法方法定义方法实现使用示例使用场景toString()方法方法

Java中List的contains()方法的使用小结

《Java中List的contains()方法的使用小结》List的contains()方法用于检查列表中是否包含指定的元素,借助equals()方法进行判断,下面就来介绍Java中List的c... 目录详细展开1. 方法签名2. 工作原理3. 使用示例4. 注意事项总结结论:List 的 contain

Java实现文件图片的预览和下载功能

《Java实现文件图片的预览和下载功能》这篇文章主要为大家详细介绍了如何使用Java实现文件图片的预览和下载功能,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... Java实现文件(图片)的预览和下载 @ApiOperation("访问文件") @GetMapping("