当前位置: 首页 > news >正文

深入理解BeanDefinition和Spring Beans

深入理解BeanDefinition和Spring Beans

引言

在Spring框架中,BeanDefinition和Spring Beans是非常重要的概念。BeanDefinition定义了Spring Bean的元数据,而Spring Beans是应用程序中的对象实例。理解BeanDefinition和Spring Beans的概念和使用方法对于开发和维护Spring应用程序非常重要。

本篇博客将深入探讨BeanDefinition和Spring Beans的概念、创建过程、属性详解以及使用BeanDefinition进行动态注册、延迟加载和依赖注入等方面的内容。

什么是BeanDefinition

BeanDefinition是Spring框架中的一个重要概念,它定义了Spring Bean的元数据信息。通过BeanDefinition,可以指定Bean的类名、作用域、构造函数参数、属性值等信息。

BeanDefinition接口定义了以下常用方法:

  • getBeanClassName():获取Bean的类名
  • getScope():获取Bean的作用域
  • setScope(String scope):设置Bean的作用域
  • getPropertyValues():获取Bean的属性值
  • setPropertyValue(String name, Object value):设置Bean的属性值
  • getConstructorArgumentValues():获取构造函数参数值
  • setConstructorArgumentValue(int index, Object value):设置构造函数参数值

Spring Beans的创建过程

Spring Beans的创建过程包括BeanDefinition的解析和实例化两个阶段。

首先,Spring容器会解析配置文件或注解,将Bean的定义转化为对应的BeanDefinition对象。然后,根据BeanDefinition的信息,通过反射机制实例化Bean对象,并进行属性注入和初始化。

在BeanDefinition解析阶段,Spring容器会读取配置文件或扫描注解,将Bean的定义转化为BeanDefinition对象。BeanDefinition对象包含了Bean的类名、作用域、构造函数参数、属性值等信息。

在Bean实例化阶段,Spring容器根据BeanDefinition的信息,通过反射机制实例化Bean对象。然后,Spring容器会根据BeanDefinition中的属性值进行属性注入,并调用Bean的初始化方法。

BeanDefinition的属性详解

BeanDefinition中常用的属性包括bean的类名、作用域、构造函数参数等。

  • Bean的类名:通过getBeanClassName()方法获取Bean的类名。通过设置Bean的类名,Spring容器可以根据类名进行反射实例化Bean对象。

  • 作用域:通过getScope()setScope(String scope)方法获取和设置Bean的作用域。常用的作用域有单例(singleton)和原型(prototype)两种。单例作用域表示Spring容器中只有一个Bean实例,而原型作用域表示每次请求都会创建一个新的Bean实例。

  • 构造函数参数:通过getConstructorArgumentValues()setConstructorArgumentValue(int index, Object value)方法获取和设置构造函数参数值。构造函数参数值可以是基本类型、引用类型或其他Bean。

  • 属性值:通过getPropertyValues()setPropertyValue(String name, Object value)方法获取和设置Bean的属性值。属性值可以是基本类型、引用类型或其他Bean。

使用BeanDefinition进行动态注册Bean

使用BeanDefinition可以在运行时动态注册Bean到Spring容器中。动态注册Bean可以灵活地根据需要创建和管理Bean对象。

下面是一个示例代码,演示如何使用BeanDefinition进行动态注册Bean:

//```java
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.context.support.GenericApplicationContext;public class DynamicBeanRegistrationExample {public static void main(String[] args) {// 创建一个GenericApplicationContext对象GenericApplicationContext context = new GenericApplicationContext();// 获取DefaultListableBeanFactory对象DefaultListableBeanFactory beanFactory = (DefaultListableBeanFactory) context.getBeanFactory();// 创建一个BeanDefinitionBuilder对象BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(MyBean.class);// 设置Bean的属性值builder.addPropertyReference("anotherBean", "anotherBean");// 注册BeanDefinition到BeanFactorybeanFactory.registerBeanDefinition("myBean", builder.getBeanDefinition());// 启动Spring应用上下文context.refresh();// 从容器中获取动态注册的BeanMyBean myBean = (MyBean) context.getBean("myBean");myBean.doSomething();}static class MyBean {private AnotherBean anotherBean;public void setAnotherBean(AnotherBean anotherBean) {this.anotherBean = anotherBean;}public void doSomething() {System.out.println("Doing something with anotherBean: " + anotherBean);}}static class AnotherBean {// ...}
}

上述示例代码中,我们首先创建了一个GenericApplicationContext对象,然后获取其对应的DefaultListableBeanFactory对象。接着,我们使用BeanDefinitionBuilder创建一个MyBeanBeanDefinition,并设置其属性值。最后,我们将BeanDefinition注册到BeanFactory中,并启动应用上下文。通过context.getBean()方法,我们可以从容器中获取动态注册的Bean,并调用其方法。

使用BeanDefinition进行动态注册Bean可以使我们在运行时根据需要创建和管理Bean对象,提供了更大的灵活性。

使用BeanDefinition进行Bean的延迟加载

BeanDefinition可以用于实现Bean的延迟加载,即在需要使用Bean时才进行实例化和初始化。通过延迟加载,可以提高应用程序的性能和资源利用率。

下面是一个示例代码,演示如何使用BeanDefinition实现Bean的延迟加载:

import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.context.support.GenericApplicationContext;public class LazyLoadingExample {public static void main(String[] args) {// 创建一个GenericApplicationContext对象GenericApplicationContext context = new GenericApplicationContext();// 获取DefaultListableBeanFactory对象DefaultListableBeanFactory beanFactory = (DefaultListableBeanFactory) context.getBeanFactory();// 创建一个BeanDefinitionBuilder对象BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(MyBean.class);// 设置Bean的属性值builder.addPropertyReference("anotherBean", "anotherBean");// 设置Bean的延迟加载属性builder.setLazyInit(true);// 注册BeanDefinition到BeanFactorybeanFactory.registerBeanDefinition("myBean", builder.getBeanDefinition());// 启动Spring应用上下文context.refresh();// 在需要使用Bean时,从容器中获取Bean并调用方法MyBean myBean = (MyBean) context.getBean("myBean");myBean.doSomething();}static class MyBean {private AnotherBean anotherBean;public void setAnotherBean(AnotherBean anotherBean) {this.anotherBean = anotherBean;}public void doSomething() {System.out.println("Doing something with anotherBean: " + anotherBean);}}static class AnotherBean {// ...}
}

上述示例代码中,我们在创建MyBeanBeanDefinition时,通过builder.setLazyInit(true)设置了Bean的延迟加载属性为true。这样,在启动应用上下文时,MyBean并不会立即被实例化和初始化,只有在需要使用它时才会进行实例化和初始化。

通过使用BeanDefinition的延迟加载属性,可以避免在应用启动时加载大量的Bean,从而提高应用程序的启动性能和资源利用率。

使用BeanDefinition进行Bean的依赖注入

BeanDefinition可以用于实现Bean的依赖注入,即在创建Bean时自动注入其他Bean的引用。通过依赖注入,可以实现组件之间的松耦合和高内聚。

下面是一个示例代码,演示如何使用BeanDefinition实现Bean的依赖注入:

import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.context.support.GenericApplicationContext;public class DependencyInjectionExample {public static void main(String[] args) {// 创建一个GenericApplicationContext对象GenericApplicationContext context = new GenericApplicationContext();// 获取DefaultListableBeanFactory对象DefaultListableBeanFactory beanFactory = (DefaultListableBeanFactory) context.getBeanFactory();// 创建一个BeanDefinitionBuilder对象BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(MyBean.class);// 设置Bean的属性值builder.addPropertyReference("anotherBean", "anotherBean");// 注册BeanDefinition到BeanFactorybeanFactory.registerBeanDefinition("myBean", builder.getBeanDefinition());// 注册另一个BeanbeanFactory.registerSingleton("anotherBean", new AnotherBean());// 启动Spring应用上下文context.refresh();// 从容器中获取Bean并调用方法MyBean myBean = (MyBean) context.getBean("myBean");myBean.doSomething();}static class MyBean {private AnotherBean anotherBean;public void setAnotherBean(AnotherBean anotherBean) {this.anotherBean = anotherBean;}public void doSomething() {System.out.println("Doing something with anotherBean: " + anotherBean);}}static class AnotherBean {// ...}
}

上述示例代码中,我们在创建MyBeanBeanDefinition时,通过builder.addPropertyReference("anotherBean", "anotherBean")设置了MyBean的属性anotherBean的引用为anotherBean。然后,我们通过beanFactory.registerSingleton("anotherBean", new AnotherBean())注册了另一个Bean。在启动应用上下文后,MyBean会自动获取anotherBean的引用,并可以使用它。

通过使用BeanDefinition进行依赖注入,可以实现Bean之间的解耦和灵活的组件配置。

BeanDefinition的扩展和自定义

除了使用Spring提供的标准的BeanDefinition之外,我们还可以扩展和自定义BeanDefinition,以满足特定的需求。

下面是一个示例代码,演示如何扩展和自定义BeanDefinition:

import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.context.support.GenericApplicationContext;public class CustomBeanDefinitionExample {public static void main(String[] args) {// 创建一个GenericApplicationContext对象GenericApplicationContext context = new GenericApplicationContext();// 获取DefaultListableBeanFactory对象DefaultListableBeanFactory beanFactory = (DefaultListableBeanFactory) context.getBeanFactory();// 创建一个自定义的BeanDefinitionCustomBeanDefinitionBuilder builder = CustomBeanDefinitionBuilder.genericBeanDefinition(MyBean.class);// 设置自定义的属性builder.setCustomProperty("customPropertyValue");
```java// 注册BeanDefinition到BeanFactorybeanFactory.registerBeanDefinition("myBean", builder.getBeanDefinition());// 启动Spring应用上下文context.refresh();// 从容器中获取Bean并调用方法MyBean myBean = (MyBean) context.getBean("myBean");myBean.doSomething();}static class MyBean {// ...}static class CustomBeanDefinitionBuilder extends BeanDefinitionBuilder {private String customProperty;private CustomBeanDefinitionBuilder(Class<?> beanClass) {super(beanClass);}public static CustomBeanDefinitionBuilder genericBeanDefinition(Class<?> beanClass) {return new CustomBeanDefinitionBuilder(beanClass);}public CustomBeanDefinitionBuilder setCustomProperty(String customProperty) {this.customProperty = customProperty;return this;}@Overridepublic BeanDefinition getBeanDefinition() {BeanDefinition beanDefinition = super.getBeanDefinition();// 添加自定义的属性到BeanDefinitionbeanDefinition.setAttribute("customProperty", customProperty);return beanDefinition;}}
}

上述示例代码中,我们创建了一个自定义的CustomBeanDefinitionBuilder,继承自BeanDefinitionBuilder。在CustomBeanDefinitionBuilder中,我们添加了一个自定义的属性customProperty,并重写了getBeanDefinition()方法,将自定义属性添加到BeanDefinition的attributes中。

通过扩展和自定义BeanDefinition,我们可以根据具体需求添加自定义属性或行为,以满足特定的业务场景。

总结

本篇博客深入理解了BeanDefinition和Spring Beans的概念、创建过程、属性详解以及使用BeanDefinition进行动态注册、延迟加载和依赖注入等方面的内容。

通过学习和掌握BeanDefinition,我们可以更好地理解和使用Spring框架,实现灵活、高效的应用程序开发。

希望本篇博客对您理解BeanDefinition和Spring Beans有所帮助,谢谢阅读!

相关文章:

深入理解BeanDefinition和Spring Beans

深入理解BeanDefinition和Spring Beans 引言 在Spring框架中&#xff0c;BeanDefinition和Spring Beans是非常重要的概念。BeanDefinition定义了Spring Bean的元数据&#xff0c;而Spring Beans是应用程序中的对象实例。理解BeanDefinition和Spring Beans的概念和使用方法对于…...

实验六 调度器-实验部分

目录 一、知识点 1.进程调度器设计的目标 1.1.进程的生命周期 1.2.用户进程创建与内核进程创建 1.3.进程调度器的设计目标 2.ucore 调度器框架 2.1.调度初始化 2.2.调度过程 2.2.1.调度整体流程 2.2.2.设计考虑要点 2.2.3.数据结构 2.2.4.调度框架应与调度算法无关…...

基于飞桨paddle波士顿房价预测练习模型测试代码

基于飞桨paddle波士顿房价预测练习模型测试代码 导入基础库 #paddle&#xff1a;飞桨的主库&#xff0c;paddle 根目录下保留了常用API的别名&#xff0c;当前包括&#xff1a;paddle.tensor、paddle.framework、paddle.device目录下的所有API&#xff1b; import paddle #Lin…...

只会“点点点”,凭什么让开发看的起你?

众所周知&#xff0c;如今无论是大厂还是中小厂&#xff0c;自动化测试基本是标配了&#xff0c;毕竟像双 11、618 这种活动中庞大繁杂的系统&#xff0c;以及多端发布、多版本、机型发布等需求&#xff0c;但只会“写一些自动化脚本”很难胜任。这一点在招聘要求中就能看出来。…...

35.图片幻灯片

图片幻灯片 html部分 <div class"carousel"><div class"image-container"><img src"./static/20180529205331_yhGyf.jpeg" alt"" srcset""><img src"./static/20190214214253_hsjqw.webp"…...

CentOS7系统Nvidia Docker容器基于TensorFlow2.12测试GPU

CentOS7系统Nvidia Docker容器基于TensorFlow1.15测试GPU 参考我的另一篇博客 1. 安装NVIDIA-Docker的Tensorflow2.12.0版本 1. 版本依赖对应关系&#xff1a;从源代码构建 | TensorFlow GPU 版本Python 版本编译器构建工具cuDNNCUDAtensorflow-2.6.03.6-3.9GCC 7.3.1Ba…...

Go 下载安装教程

1. 下载地址&#xff1a;The Go Programming Language (google.cn) 2. 下载安装包 3. 安装 &#xff08;1&#xff09;下一步 &#xff08;2&#xff09;同意 &#xff08;3&#xff09;修改安装路径&#xff0c;如果不修改&#xff0c;直接下一步 更改后&#xff0c;点击下一…...

InnoDB数据存储结构

一. InnoDB的数据存储结构&#xff1a;页 索引是在存储引擎中实现的&#xff0c;MySQL服务器上的存储引擎负责对表中数据的读取和写入工作。不同存储引擎中存放的格式一般不同的&#xff0c;甚至有的存储引擎比如Memory都不用磁盘来存储数据&#xff0c;这里讲讲InooDB存储引擎…...

基于ts的浏览器缓存工具封装(含源码)

cache.ts缓存工具 浏览器缓存工具封装实现使用方法示例代码 浏览器缓存工具封装 在前端开发中&#xff0c;经常会遇到需要缓存数据的情况&#xff0c;例如保存用户的登录状态、缓存部分页面数据等 但有时候需要缓存一些复杂的对象&#xff0c;例如用户信息对象、设置配置等。…...

GIT涵盖工作中用的相关指令

git安装一直默认点击下去&#xff0c;安装完成&#xff0c;右键会看见gitBash git --version 查看git安装的版本 使用git前配置git git config --global user.name 提交人姓名 git config --global user.email 提交人邮箱 git config --list 查看git配置信息 使用git中配置…...

【如何训练一个中英翻译模型】LSTM机器翻译seq2seq字符编码(一)

系列文章 【如何训练一个中英翻译模型】LSTM机器翻译seq2seq字符编码&#xff08;一&#xff09; 【如何训练一个中英翻译模型】LSTM机器翻译模型训练与保存&#xff08;二&#xff09; 【如何训练一个中英翻译模型】LSTM机器翻译模型部署&#xff08;三&#xff09; 【如何训…...

[JAVAee]文件操作-IO

本文章讲述了通过java对文件进行IO操作 IO:input/output,输入/输出. 建议配合文章末尾实例食用 目录 文件 文件的管理 文件的路径 文件的分类 文件系统的操作 File类的构造方法 File的常用方法 文件内容的读写 FileInputStream读取文件 构造方法 常用方法 Scan…...

【数据集】3小时尺度降水数据集-MSWEPV2

1 MSWEP V2 precipitation product 官网-MSWEP V2降水产品 参考...

Springboot之把外部依赖包纳入Spring容器管理的两种方式

前言 在Spring boot项目中&#xff0c;凡是标记有Component、Controller、Service、Configuration、Bean等注解的类&#xff0c;Spring boot都会在容器启动的时候&#xff0c;自动创建bean并纳入到Spring容器中进行管理&#xff0c;这样就可以使用Autowired等注解&#xff0c;…...

更安全,更省心丨DolphinDB 数据库权限管理系统使用指南

在数据库产品使用过程中&#xff0c;为保证数据不被窃取、不遭破坏&#xff0c;我们需要通过用户权限来限制用户对数据库、数据表、视图等功能的操作范围&#xff0c;以保证数据库安全性。为此&#xff0c;DolphinDB 提供了具备以下主要功能的权限管理系统&#xff1a; 提供用户…...

WPS本地镜像化在线文档操作以及样例

一个客户项目有引进在线文档操作需求&#xff0c;让我这边做一个demo调研下&#xff0c;给我的对接文档里有相关方法的说明&#xff0c;照着对接即可。但在真正对接过程中还是踩过不少坑&#xff0c;这儿对之前的对接工作做个记录。 按照习惯先来一个效果&#xff1a; Demo下载…...

STM32 Flash学习(一)

STM32 FLASH简介 不同型号的STM32&#xff0c;其Flash容量也不同。 MiniSTM32开发板选择的STM32F103RCT6的FLASH容量为256K字节&#xff0c;属于大容量产品。 STM32的闪存模块由&#xff1a;主存储器、信息块和闪存存储器接口寄存器等3部分组成。 主存储器&#xff0c;该部分…...

Spring中IOC容器常用的接口和具体的实现类

在Spring框架没有出现之前&#xff0c;在Java语言中&#xff0c;程序员们创建对象一般都是通过关键字new来完成&#xff0c;那时流行一句话“万物即可new&#xff0c;包括女朋友”。但是这种创建对象的方式维护成本很高&#xff0c;而且对于类之间的相互关联关系很不友好。鉴于…...

【MySQL】索引特性

​&#x1f320; 作者&#xff1a;阿亮joy. &#x1f386;专栏&#xff1a;《零基础入门MySQL》 &#x1f387; 座右铭&#xff1a;每个优秀的人都有一段沉默的时光&#xff0c;那段时光是付出了很多努力却得不到结果的日子&#xff0c;我们把它叫做扎根 目录 &#x1f449;没…...

【深度学习笔记】动量梯度下降法

本专栏是网易云课堂人工智能课程《神经网络与深度学习》的学习笔记&#xff0c;视频由网易云课堂与 deeplearning.ai 联合出品&#xff0c;主讲人是吴恩达 Andrew Ng 教授。感兴趣的网友可以观看网易云课堂的视频进行深入学习&#xff0c;视频的链接如下&#xff1a; 神经网络和…...

如何在macOS上免费解锁QQ音乐加密文件:完整指南

如何在macOS上免费解锁QQ音乐加密文件&#xff1a;完整指南 【免费下载链接】QMCDecode QQ音乐QMC格式转换为普通格式(qmcflac转flac&#xff0c;qmc0,qmc3转mp3, mflac,mflac0等转flac)&#xff0c;仅支持macOS&#xff0c;可自动识别到QQ音乐下载目录&#xff0c;默认转换结果…...

微信小程序3D开发框架技术对比:XR-Frame与threejs-miniprogram

随着微信小程序逐步支持3D渲染与AR能力&#xff0c;开发者面临两个主要官方方案&#xff1a;自研的XR-Frame和适配Three.js的threejs-miniprogram。本文将从架构设计、渲染机制、功能集成、开发模式及适用场景等维度进行技术分析&#xff0c;为技术选型提供参考。一、XR-Frame&…...

OpenClaw用户如何快速接入Taotoken并开始Agent工作流

&#x1f680; 告别海外账号与网络限制&#xff01;稳定直连全球优质大模型&#xff0c;限时半价接入中。 &#x1f449; 点击领取海量免费额度 OpenClaw用户如何快速接入Taotoken并开始Agent工作流 对于使用OpenClaw框架构建AI智能体的开发者而言&#xff0c;快速接入稳定、多…...

0.2毫秒快速启动的操作系统

在工业控制以及航空航天等核心场景&#xff0c;极速启动就是高可靠系统的生命线。0.2毫秒超快启动搭配硬件看门狗&#xff0c;让设备在掉电重启、异常恢复时瞬时归位&#xff0c;关键任务永不延误&#xff01; https://www.bilibili.com/video/BV11mLY6VERt/?spm_id_from333.1…...

Godot4 2D游戏开发避坑指南:TileMap绘制、节点顺序与相机设置的三个常见问题

Godot4 2D游戏开发避坑指南&#xff1a;TileMap绘制、节点顺序与相机设置的三个常见问题当你第一次用Godot4完成一个2D场景搭建时&#xff0c;那种成就感往往会被几个突如其来的bug瞬间击碎——角色神秘消失、背景纹丝不动、屏幕边缘出现诡异黑边。这些问题看似简单&#xff0c…...

长期使用Token Plan套餐在项目开发中的成本观察

&#x1f680; 告别海外账号与网络限制&#xff01;稳定直连全球优质大模型&#xff0c;限时半价接入中。 &#x1f449; 点击领取海量免费额度 长期使用Token Plan套餐在项目开发中的成本观察 在AI驱动的项目开发中&#xff0c;成本控制与预算管理是团队负责人必须面对的现实…...

关联规则挖掘在Calabi-Yau流形Hodge数分析中的应用与复现

1. 项目概述&#xff1a;当数据挖掘遇见高维几何在理论物理和代数几何的交叉领域&#xff0c;Calabi-Yau流形一直扮演着核心角色。这些具有特殊拓扑结构的空间&#xff0c;不仅是弦理论中额外维度紧化的关键候选者&#xff0c;其本身丰富的数学性质也吸引着无数研究者。然而&am…...

终极键盘重映射解决方案:3分钟实现职业级游戏操作精度

终极键盘重映射解决方案&#xff1a;3分钟实现职业级游戏操作精度 【免费下载链接】socd Key remapper for epic gamers 项目地址: https://gitcode.com/gh_mirrors/so/socd 在激烈的游戏对抗中&#xff0c;你是否曾因键盘按键冲突而错失关键操作&#xff1f;当同时按下…...

别让依赖毁了你的实验:记一次Vision Mamba复现中causal_conv1d与mamba-ssm的版本“打架”事件

Vision Mamba复现实战&#xff1a;破解依赖冲突的工程化解决方案在深度学习项目的复现过程中&#xff0c;依赖管理往往是最容易被忽视却又最常导致问题的环节。最近在复现Vision Mamba模型时&#xff0c;我遭遇了一场典型的Python依赖"战争"——causal_conv1d与mamba…...

Sora 2原生MP4输出不兼容Premiere Pro?揭秘H.264/H.265封装层4大隐性缺陷(附MediaInfo诊断模板+自动修复脚本)

更多请点击&#xff1a; https://codechina.net 第一章&#xff1a;Sora 2原生MP4输出不兼容Premiere Pro的根源定位 Sora 2生成的原生MP4文件虽符合ISO/IEC 14496-14规范&#xff0c;但其底层封装结构与Adobe Premiere Pro对时间码、元数据及视频流编码参数的严格校验逻辑存在…...