Spring为什么要专门定义BeanDefinition ,有Class不行吗?

news2024/11/17 16:49:12

前言

创建一个Java Bean,大概是下面这个流程:

在这里插入图片描述

我们写的Java文件,会编译为Class文件,运行程序,类加载器会加载Class文件,放入JVM的方法区,我们就可以愉快的new对象了。

创建一个Spring Bean,大概是下面这个流程:

在这里插入图片描述

我们写的Java文件,会编译为Class文件,运行程序,类加载器会加载Class文件,放入JVM的方法区,这一步还是保持不变(当然这个也没办法变。。。) 下面就是Spring的事情了,Spring会解析我们的配置类(配置文件),假设现在只配置了A,解析后,Spring会把A的BeanDefinition放到一个map中去,随后,由一个一个的BeanPostProcessor进行加工,最终把经历了完整的Spring生命周期的Bean放入了singleObjects。

BeanDefinition 介绍

借助 IDE ,打开 BeanDefinition 的接口定义,从方法列表上看,BeanDefinition 整体包含以下几个部分:

  • Bean 的类信息 - 全限定类名 ( beanClassName )
  • Bean 的属性 - 作用域 ( scope ) 、是否默认 Bean ( primary ) 、描述信息 ( description ) 等
  • Bean 的行为特征 - 是否延迟加载 ( lazy ) 、是否自动注入 ( autowireCandidate ) 、初始化 / 销毁方法 ( initMethod / destroyMethod ) 等
  • Bean 与其他 Bean 的关系 - 父 Bean 名 ( parentName ) 、依赖的 Bean ( dependsOn ) 等
  • Bean 的配置属性 - 构造器参数 ( constructorArgumentValues ) 、属性变量值 ( propertyValues ) 等

BeanDefinition 描述了 SpringFramework 中 bean 的元信息,它包含 bean 的类信息、属性、行为、依赖关系、配置信息等。BeanDefinition 具有层次性,并且可以在 IOC 容器初始化阶段被 BeanDefinitionRegistryPostProcessor 构造和注册,被 BeanFactoryPostProcessor 拦截修改等。

两者对比

  • BeanDefinition是Spring框架中描述和定义Bean的元数据对象,用于配置和管理Bean的创建和生命周期。
  • Class对象是Java反射机制中表示类的元数据对象,用于访问和操作类的静态结构。
  • BeanDefinition提供了更高级的抽象和配置能力,而Class对象提供了更底层的操作能力。
  • 在Spring容器中,BeanDefinition和Class对象之间存在关联,BeanDefinition使用Class对象来创建和管理Bean的实例。

原因理解1

在Spring框架中,BeanDefinition有着非常重要的作用。它是Spring对Bean配置的内部表示,包含了需要创建一个Bean的绝大部分信息。BeanDefinition用于告诉Spring如何创建一个Bean,包括Bean的类型、生命周期、依赖等等。

如果我们只使用Class来定义Bean,那么我们只能获得Bean的类型信息,无法得知其他信息,比如:

  • Bean的作用域(单例、原型等)。
  • Bean的构造函数参数或者属性的值,这些值可能来自于其他Bean或者配置文件。
  • Bean的初始化方法和销毁方法。
  • Bean是否懒加载。
  • Bean的别名。

这些信息都是Spring在创建和管理Bean时需要的,而且这些信息都不能通过Class对象获取,因此Spring定义了BeanDefinition来保存这些信息。

同时,BeanDefinition还提供了一种抽象,使得Spring能够支持不同的配置方式,比如XML配置、注解配置,甚至是Groovy配置。所有这些配置最终都会被转换成BeanDefinition,这让Spring的内部处理变得更加统一和简洁。

所以,BeanDefinition的设计是非常有必要的,它使得Spring具有了非常强大的灵活性和可扩展性。

原因理解2

在Spring框架中,专门定义BeanDefinition的目的是为了提供更灵活和可配置的方式来定义和管理Bean的元数据。虽然使用Class来表示Bean的类型是可能的,但是仅仅使用Class无法满足一些高级需求和复杂场景。

以下是一些原因和优势,解释为什么要专门定义BeanDefinition

  1. 元数据的扩展性:BeanDefinition允许在定义Bean时包含更多的元数据信息,例如Bean的作用域、初始化方法、销毁方法、依赖关系等。这些元数据将会在容器启动时被解析和应用。通过BeanDefinition,可以提供更多的配置选项和灵活性,以满足不同场景下的需求。

  2. 多种配置方式:BeanDefinition不仅支持使用Class来定义Bean的类型,还支持其他配置方式,如XML配置、注解配置、Java配置等。这样可以根据具体的需求和喜好选择最适合的配置方式。通过不同的配置方式,可以更灵活地定义和管理Bean。

  3. 提供统一的Bean定义模型:BeanDefinition提供了一个统一的模型来描述Bean的定义,不受具体实现类的限制。它使得不同的配置方式和不同的实现可以共享相同的Bean定义模型,从而实现更好的解耦和可扩展性。

  4. 支持非实例化Bean:BeanDefinition可以表示非实例化的Bean,这些Bean可能是抽象的、接口的或基于工厂方法创建的。使用BeanDefinition可以描述这些非实例化的Bean,并在需要时进行实例化。

  5. 提供更多的编程接口和扩展点:Spring框架提供了许多与BeanDefinition相关的编程接口和扩展点,例如BeanPostProcessorBeanFactoryPostProcessor等。通过这些接口,可以在Bean的创建和初始化过程中插入自定义逻辑,实现更高级的功能,如AOP、事务管理等。

总之,专门定义BeanDefinition的目的是为了提供更灵活、可配置和扩展的方式来描述和管理Bean的元数据。它使得Spring框架能够更好地支持不同的配置方式和复杂的应用场景,提供了统一的Bean定义模型和丰富的编程接口。

原因理解3

Spring 定义 BeanDefinition 而不是直接使用 Class 的主要原因有:

  1. 解耦合

Spring 的 IoC 容器需要管理各种 Bean,如果直接使用 Class,就需要容器直接依赖具体的 Bean Class。定义 BeanDefinition 后,容器只依赖 BeanDefinition,不依赖具体 Class,降低了耦合。

  1. 提高灵活性

BeanDefinition 中可以定义 Bean 的各种属性,如是否单例、初始化方法、依赖关系等,都可以通过配置灵活控制,不需要修改代码。

  1. 统一管理

将 Bean 的定义统一提取到配置文件中,便于集中管理。

  1. 方便扩展

可以基于 BeanDefinition 进行扩展,例如修改其属性、添加其他信息等。

  1. Bean 实例化提前

由于有了 BeanDefinition,容器初始化时就可以一次性实例化所有的 Bean。如果直接使用 Class,则只有真正使用时才会实例化。

  1. 避免循环依赖

有了 BeanDefinition 后,容器初始化时实例化 Bean 可以分两步:先实例化,再设置属性。这样可以处理循环依赖。

总之,引入 BeanDefinition 主要是为了实现 IoC 容器的功能,提高灵活性和可扩展性。如果直接使用 Class 会导致容器与 Bean 之间过于紧密的耦合。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

项目总结知识点记录(二)

1.拦截器实现验证用户是否登录: 拦截器类:实现HandlerInterception package com.yx.interceptor;import org.springframework.web.servlet.HandlerInterceptor; import org.springframework.web.servlet.ModelAndView;import javax.servlet.http.HttpS…

Mybatis+MybatisPlus拦截器实战之数据的加解密和脱敏

文章目录 一、前言二、拦截器简介三、代码目录结构简介四、核心代码讲解4.1 application.yml文件4.2 自定义注解4.2.1 SensitiveEntity4.2.2 SensitiveData4.2.3 MaskedEntity4.2.4 MaskedField4.2.5 MaskedMethod 4.3 Mybatis-Plus 拦截器数据自动加密4.4 Mybatis 打印完整sql…

7年经验之谈 —— 如何实现高效的Web自动化测试?

随着互联网的快速发展,Web应用程序的重要性也日益凸显。为了保证Web应用程序的质量和稳定性,Web自动化测试成为必不可少的一环。然而,如何实现高效的Web自动化测试却是一个值得探讨的课题。 首先,选择合适的测试工具是关键。市面…

低通滤波器和高通滤波器

应用于图像低通滤波器和高通滤波器的实现 需要用到傅里叶变换 #include <opencv2/opencv.hpp> #include <Eigen> #include <iostream> #include <vector> #include <cmath> #include <complex>#define M_PI 3.14159265358979323846…

五、多表查询-3.4连接查询-联合查询union

一、概述 二、演示 【例】将薪资低于5000的员工&#xff0c;和 年龄大于50岁的 员工全部查询出来 1、查询薪资低于5000的员工 2、查询年龄大于50岁的员工 3、将薪资低于5000的员工&#xff0c;和 年龄大于50岁的 员工全部查询出来&#xff08;把上面两部分的结果集直接合并起…

最新敏感信息和目录收集技术

敏感信息和目录收集 目标域名可能存在较多的敏感目录和文件&#xff0c;这些敏感信息很可能存在目录穿越漏洞、文件上传漏洞&#xff0c;攻击者能通过这些漏洞直接下载网站源码。搜集这些信息对之后的渗透环节有帮助。通常&#xff0c;扫描检测方法有手动搜寻和自动工具查找两…

requestAnimationFrame(RAF)

1、RAF介绍 requestAnimateFrame&#xff08;RAF&#xff09;动画帧&#xff0c;是一个做动画的API。 如果想要一个动画流畅&#xff0c;就需要以60帧/s来更新视图&#xff0c;那么一次视图的更新就是16.67ms。 想要达到上述目标&#xff0c;可以通过setTimeout定时器来手动控…

JSON文件教程之【jsoncpp源码编译】

目录 1 数据下载(jsoncpp源码)2 文件编译内容: JSON文件的读取与保存可以使用jsoncpp库来实现,这里介绍该库的下载及编译方法。 1 数据下载(jsoncpp源码) 数据下载:Github地址 图1 github源码示意图 2 文件编译 2.1 点击Download ZIP,下载源码。 图2 压缩包数据 2.2 将压…

在 macOS 中安装 TensorFlow 1g

tensorflow 需要多大空间 pip install tensorflow pip install tensorflow Looking in indexes: https://pypi.douban.com/simple/ Collecting tensorflowDownloading https://pypi.doubanio.com/packages/1a/c1/9c14df0625836af8ba6628585c6d3c3bf8f1e1101cafa2435eb28a7764…

2022年06月 C/C++(四级)真题解析#中国电子学会#全国青少年软件编程等级考试

第1题&#xff1a;公共子序列 我们称序列Z < z1, z2, …, zk >是序列X < x1, x2, …, xm >的子序列当且仅当存在 严格上升 的序列< i1, i2, …, ik >&#xff0c;使得对j 1, 2, … ,k, 有xij zj。比如Z < a, b, f, c > 是X < a, b, c, f, b, …

软考:中级软件设计师:关系代数:中级软件设计师:关系代数,规范化理论函数依赖,它的价值和用途,键,范式,模式分解

软考&#xff1a;中级软件设计师:关系代数 提示&#xff1a;系列被面试官问的问题&#xff0c;我自己当时不会&#xff0c;所以下来自己复盘一下&#xff0c;认真学习和总结&#xff0c;以应对未来更多的可能性 关于互联网大厂的笔试面试&#xff0c;都是需要细心准备的 &…

一篇文章带你彻底了解Java常用的设计模式

文章目录 前言1. 工厂模式使用示例代码优势 2. 单例模式说明使用示例代码优势 3. 原型模式使用示例代码优势 4. 适配器模式使用示例代码优势 5. 观察者模式使用示例代码优势 6. 策略模式使用示例代码优势 7. 装饰者模式使用示例代码优势 8. 模板方法模式使用示例代码优势 总结 …

python-数据可视化-下载数据-CSV文件格式

数据以两种常见格式存储&#xff1a;CSV和JSON CSV文件格式 comma-separated values import csv filename sitka_weather_07-2018_simple.csv with open(filename) as f:reader csv.reader(f)header_row next(reader)print(header_row) # [USW00025333, SITKA AIRPORT, A…

YOLO目标检测——皮肤检测数据集下载分享

数据集点击下载&#xff1a;YOLO皮肤检测数据集Face-Dataset.rar

springboot源码方法

利用LinkedHashSet移除List重复的数据protected final <T> List<T> removeDuplicates(List<T> list) {return new ArrayList<>(new LinkedHashSet<>(list));} SpringFactoriesLoader#loadFactoryNames 加载配置文件

常见的移动端布局

流式布局&#xff08;百分比布局&#xff09; 使用百分比、相对单位&#xff08;如 em、rem&#xff09;等来设置元素的宽度&#xff0c;使页面元素根据视口大小的变化进行调整。这种方法可以实现基本的自适应效果&#xff0c;但可能在不同设备上显示不一致。 <!DOCTYPE ht…

ctfshow-web14

0x00 前言 CTF 加解密合集CTF Web合集 0x01 题目 0x02 Write Up 首先看到这个&#xff0c;swith&#xff0c;那么直接输入4&#xff0c;则会打印$url的值 然后访问一下 查看一下&#xff0c;发现完整的请求是http://c7ff9ed6-dccd-4d01-907a-f1c61c016c15.challenge.ctf.sho…

python网络爬虫指南二:多线程网络爬虫、动态内容爬取(待续)

文章目录 一、多线程网络爬虫1.1 线程的基础内容、GIL1.2 创建线程的两种方式1.3 threading.Thread类1.4 线程常用方法和锁机制1.5 生产者-消费者模式1.5.1 生产者-消费者模式简介1.5.2 Condition 类协调线程 1.6 线程中的安全队列1.6 多线程爬取王者荣耀壁纸1.6.1 网页分析1.6…

2023-8-26 模拟散列表

题目链接&#xff1a;模拟散列表 拉链法 #include <iostream> #include <cstring>using namespace std;const int N 100010;int h[N], e[N], ne[N], idx;void insert(int x) {int k (x % N N) % N;e[idx] x;ne[idx] h[k];h[k] idx;idx ; }bool query(int …

智慧县城,乍暖还寒风起时

提起中国的区域数字化&#xff0c;我们大概率会关注两个维度。一个是北上广深为代表的超大城市&#xff0c;这里的智慧城市落地是风向标、排头兵&#xff1b;另一个是乡村的数字化、智能化&#xff0c;作为区域智能升级的最小单位&#xff0c;乡村的典型性更强&#xff0c;也符…