文章目录
一、BeanDefinition 的概述
1.1 BeanDefinition 的定位
核心组件的介绍:
- BeanFactory(Bean 工厂):BeanFactory 是 Spring 框架的核心接口,负责管理应用中的 Bean 实例。它是 Spring IoC 容器的基础,提供了一种配置机制来管理 Bean 的生命周期和依赖关系。
- ApplicationContext(应用上下文):ApplicationContext 是 BeanFactory 的子接口,它扩展了 BeanFactory 的功能,提供了更多的企业级特性,例如国际化、事件传播、资源加载等。ApplicationContext 是 Spring 中最常用的 IoC 容器,负责加载配置文件、管理 Bean 实例并提供各种服务。
- BeanDefinition(Bean 定义):BeanDefinition 定义了 Bean 的配置元数据,包括类名、依赖关系、初始化方法、销毁方法等。BeanFactory 使用 BeanDefinition 来创建 Bean 实例。
- FactoryBean:FactoryBean 是一个特殊的 Bean,它实现了 FactoryBean 接口,并且负责返回其他 Bean 的实例。FactoryBean 允许开发者在创建 Bean 实例的过程中进行一些定制化的操作,例如延迟加载、按需初始化等。
- Bean:Bean 是 Spring 管理的对象实例,它们是应用程序的核心组件,通过 Spring IoC 容器来管理和配置。
组件之间的关系 :
1.2 BeanDefition 的作用
- 定义 Bean 的配置元数据:BeanDefinition 定义了每个 Bean 的配置信息,包括类名、依赖关系、初始化方法、销毁方法等。它描述了如何创建和配置一个特定的 Bean 实例。
- 实例化 Bean:BeanDefinition 充当了实例化 Bean 的指南。Spring IoC 容器根据 BeanDefinition 中的配置信息来创建 Bean 实例,并在需要时将其初始化。
- 管理 Bean 的生命周期:BeanDefinition 中定义了 Bean 的生命周期方法,如初始化方法和销毁方法,Spring IoC 容器负责调用这些方法,以确保 Bean 在适当的时候进行初始化和销毁。
- 处理 Bean 的依赖关系:BeanDefinition 中包含了 Bean 之间的依赖关系,Spring IoC 容器使用这些信息来解析和管理 Bean 之间的依赖关系,确保它们在合适的时间被注入和初始化。
- 支持各种配置方式: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定义 的关键类区别:
- RootBeanDefinition: -
RootBeanDefinition
是AbstractBeanDefinition
的直接子类。- 通常用于定义独立的 Bean,即非继承关系的 Bean。- 可以通过setBeanClass(Class beanClass)
方法设置 Bean 的类型,通过setConstructorArgumentValues(ConstructorArgumentValues constructorArgumentValues)
设置构造函数参数值,以及通过其他方法设置 Bean 的属性、作用域、依赖关系等。 - ChildBeanDefinition: -
ChildBeanDefinition
也是AbstractBeanDefinition
的直接子类。- 用于定义继承关系中的子 Bean,即通过 标签的parent
属性来继承父 Bean 的配置信息的子 Bean。- 与RootBeanDefinition
相比,ChildBeanDefinition
可以继承父 Bean 的属性配置,并可以覆盖或添加新的属性。- 通常不直接实例化ChildBeanDefinition
,而是通过 XML 配置文件或者 Java 代码中的父子 Bean 定义来间接使用。 - AbstractBeanDefinition: -
AbstractBeanDefinition
是一个抽象类,用于表示 Bean 的抽象定义,定义了 Bean 的基本属性和行为 。- 它定义了 Bean 的基本属性和行为,包括类、作用域、构造函数参数、属性值、初始化方法、销毁方法等。-RootBeanDefinition
和ChildBeanDefinition
都是AbstractBeanDefinition
的子类,因此它们继承了AbstractBeanDefinition
中定义的一些属性和方法,如setBeanClass()
、setScope()
等。
仅仅展示抽象类AbstractBeanDefinition的定义Bean的主要行为。想要了解子类RootBeanDefinition和子类ChildBeanDefinition,以及其它定义的Bean行为的读者,可自行查看相应的源码,进行解读。
2.2.2 setBeanClassName()
2.2.3 getDependsOn()
2.2.4 setScope()
2.3 BeanDefinition 运用的设计模式
最突出的设计模式包括:
- 模板方法模式: -
AbstractBeanDefinition
定义了一个模板方法validate()
,该方法规定了 Bean 定义的验证流程,但是具体的验证细节交由子类实现。这符合模板方法模式的思想,即定义一个算法的骨架,将具体步骤的实现延迟到子类中。 - 工厂方法模式: -
AbstractBeanDefinition
是一个抽象类,其中包含一个抽象的工厂方法getBeanClass()
,用于获取 Bean 的类对象。具体的 Bean 类型由子类提供,符合工厂方法模式的定义,即将对象的创建延迟到子类中。 - 策略模式: -
AbstractBeanDefinition
中的属性scope
、lazyInit
等代表了不同的策略,决定了 Bean 的作用域和是否延迟初始化。这些属性的值可以根据具体情况动态地设置,从而改变 Bean 的行为,符合策略模式的思想,即定义一系列算法,将它们封装起来,并且使它们可以相互替换。 - 装饰器模式: - Spring 中的 Bean 定义可能会有各种各样的装饰器(例如:属性装饰器、生命周期装饰器等),用于增强或修改 Bean 的行为。
AbstractBeanDefinition
可以作为装饰器的基类,通过组合的方式实现装饰器模式,为 Bean 定义提供灵活的扩展机制。 - 建造者模式: - 在 Spring 中,通过
BeanDefinitionBuilder
类来构建AbstractBeanDefinition
实例,它使用了建造者模式,通过一系列的方法链式调用来设置AbstractBeanDefinition
的属性,并最终构建出一个完整的 Bean 定义对象。
2.4 BeanDefinition 的注册和解析过程
BeanDefinition 的注册过程通常由
BeanDefinitionRegistry
接口及其实现类(如
DefaultListableBeanFactory
)负责。
2.4.1 BeanDefinitionRegistry接口
2.4.2 DefaultListableBeanFactory实现类
查看
DefaultListableBeanFactory
类的
registerBeanDefinition()
方法,该方法用于向容器注册 BeanDefinition。其它方法读者感兴趣,可自行查看源码。
三、实际案例分析
通过一个简单的健身房会员管理系统来演示如何在日常开发中使用BeanDefinition。
需求:
- 每个会员都有一个唯一的会员编号、姓名和注册日期。
- 系统需要能够添加新会员、查询会员信息和删除会员。
- 会员类:Member
publicclassMember{privateint memberId;privateString name;privateLocalDate registrationDate;// 省略构造函数、getter和setter方法}
- 会员管理服务类:MemberManagementService
importjava.util.HashMap;importjava.util.Map;publicclassMemberManagementServiceImpl{privateMap<Integer,Member> members =newHashMap<>();privateint nextMemberId =1;/**
* 添加新会员
*/publicvoidaddMember(String name){Member member =newMember();
member.setMemberId(nextMemberId++);
member.setName(name);
member.setRegistrationDate(LocalDate.now());
members.put(member.getMemberId(), member);}/**
* 查询会员信息
*/publicMembergetMember(int memberId){return members.get(memberId);}/**
* 删除会员
*/publicvoidremoveMember(int memberId){
members.remove(memberId);}}
- Spring配置类:AppConfig
importorg.springframework.context.annotation.Bean;importorg.springframework.context.annotation.Configuration;/**
* 使用了BeanDefinition来声明了 MemberManagementService 的 Bean
*/@ConfigurationpublicclassAppConfig{@BeanpublicMemberManagementServicememberManagementService(){returnnewMemberManagementService();}}
- 应用程序入口类:Main
importorg.springframework.context.ApplicationContext;importorg.springframework.context.annotation.AnnotationConfigApplicationContext;publicclassMain{publicstaticvoidmain(String[] args){ApplicationContext context =newAnnotationConfigApplicationContext(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);}}
两周年 ~ 一起努力叭
版权归原作者 忆~遂愿 所有, 如有侵权,请联系我们删除。