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

【Spring源码解读!底层原理进阶】【下】探寻Spring内部:BeanFactory和ApplicationContext实现原理揭秘✨

 🎉🎉欢迎光临🎉🎉

🏅我是苏泽,一位对技术充满热情的探索者和分享者。🚀🚀

🌟特别推荐给大家我的最新专栏《Spring 狂野之旅:底层原理高级进阶》 🚀

本专栏纯属为爱发电永久免费!!!

这是苏泽的个人主页可以看到我其他的内容哦👇👇

努力的苏泽icon-default.png?t=N7T8http://suzee.blog.csdn.net/


 

目录

深挖ApplicationContext的高级特性

环境与配置文件的灵活管理

Profile的工作原理

使用PropertySources优雅地管理配置

数据访问与事务管理的抽象

数据访问异常的统一处理

声明式事务管理的实现机制

实践:验证声明式事务的工作原理

第五章:Spring表达式语言(SpEL)

SpEL的设计目的与应用场景

SpEL的核心语法与功能

如何通过SpEL实现动态配置

总结:BeanFactory与ApplicationContext的精髓

如何继续深入学习Spring


深挖ApplicationContext的高级特性

在Spring框架中,ApplicationContext 被誉为Spring的心脏,负责管理Bean的生命周期和提供配置框架的各种高级特性。本篇博客将深入探讨ApplicationContext的几个高级特性,包括环境与配置文件的灵活管理、Profile的工作原理、使用PropertySources管理配置的优雅方式,以及数据访问与事务管理的抽象和实现机制。我们不仅会通过源码解读这些特性背后的设计思想,还会提供代码示例来验证我们的观点。

环境与配置文件的灵活管理

Spring允许开发者通过多种方式灵活管理应用的配置,包括但不限于属性文件、YAML文件、环境变量和命令行参数。这一切得益于EnvironmentPropertySources抽象。

Profile的工作原理

Profile允许开发者为不同的环境(如开发、测试、生产)定义不同的配置。通过激活特定的Profile,可以加载相应环境的配置。

@Configuration
@Profile("dev")
public class DevConfig {// 配置类内容
}

上述代码展示了如何定义一个仅在开发环境下激活的配置类。Spring根据当前激活的Profile来决定是否加载该配置类。

使用PropertySources优雅地管理配置

PropertySources是Spring环境抽象的一部分,它允许开发者从多个来源灵活地加载配置

Environment env = applicationContext.getEnvironment();
String property = env.getProperty("some.property");

通过Environment接口,可以方便地访问配置属性。

数据访问与事务管理的抽象

Spring提供了一套与具体技术无关的数据访问异常层次结构,使得异常处理更加统一和简便。

数据访问异常的统一处理

Spring将底层数据访问技术(如JDBC、Hibernate等)抛出的异常转换为DataAccessException体系中的异常,从而避免了与特定技术的耦合。

声明式事务管理的实现机制

Spring的声明式事务管理依赖于AOP(面向切面编程),允许开发者通过声明的方式来管理事务,而无需编写传统的事务管理代码。

@Transactional
public void someTransactionalMethod() {// 方法体
}

上述@Transactional注解表明该方法应在事务的上下文中运行。Spring在幕后自动创建和管理事务。

实践:验证声明式事务的工作原理

为了进一步理解声明式事务的工作原理,我们可以编写一个简单的测试用例来验证事务的行为。

 

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = {TransactionConfig.class})
public class TransactionalTest {@Autowiredprivate TestService testService;@Test(expected = DataAccessException.class)public void testTransactionalMethod() {testService.someTransactionalMethod();}
}

在这个测试中,someTransactionalMethod方法在遇到数据访问异常时能够回滚事务。

如果事务正确回滚,那么这个测试应该通过,因为我们期望遇到DataAccessException

为了演示和验证事务的回滚机制,我们可以通过一个简单的Spring Boot应用中的服务层方法来模拟。假设我们有一个UserService,它负责处理用户的注册逻辑。在用户注册的过程中,我们故意引入一个数据访问异常,以触发事务回滚。

首先,我们定义一个简单的用户实体User和对应的数据访问接口UserRepository(这里只是为了演示,不涉及具体的数据库操作代码):

@Entity
public class User {@Id@GeneratedValue(strategy = GenerationType.AUTO)private Long id;private String username;// 省略构造函数、Getter和Setter方法
}public interface UserRepository extends JpaRepository<User, Long> {// 这里可以添加一些自定义的数据访问方法
}

接下来,我们实现UserService,并在其中添加一个注册用户的方法,该方法会故意抛出一个DataAccessException来模拟数据访问异常:

@Service
public class UserService {@Autowiredprivate UserRepository userRepository;@Transactionalpublic void registerUser(User user) {// 正常的用户注册逻辑userRepository.save(user);System.out.println("用户注册成功");// 故意抛出数据访问异常来模拟异常情况if (user.getUsername().equals("triggerException")) {throw new DataAccessException("模拟数据访问异常") {};}}
}

最后,我们编写一个测试用例来验证当registerUser方法遇到数据访问异常时,事务是否能够正确回滚:

@RunWith(SpringRunner.class)
@SpringBootTest
public class UserServiceTest {@Autowiredprivate UserService userService;@Autowiredprivate UserRepository userRepository;@Test(expected = DataAccessException.class)public void testRegisterUserWithException() {User user = new User();user.setUsername("triggerException");try {userService.registerUser(user);} finally {// 验证用户没有被保存到数据库,即事务回滚了Optional<User> foundUser = userRepository.findByUsername("triggerException");assertFalse(foundUser.isPresent());System.out.println("事务回滚,用户未被保存到数据库");}}
}

我们首先尝试注册一个用户名为triggerException的用户,这将触发我们在registerUser方法中故意设置的数据访问异常。根据@Transactional注解的工作原理,一旦方法抛出异常,所有的数据变更都应该被回滚。

最后在捕获异常后,我们检查数据库是否存在该用户记录,找不到的,这样就证明事务确实被回滚了

第五章:Spring表达式语言(SpEL)

在本章中,我们将探讨Spring表达式语言(SpEL)的设计目的、应用场景以及它的核心语法与功能。SpEL是一个强大的表达式语言,它可以在Spring框架中被广泛地应用于动态配置和表达式求值的场景。

SpEL的设计目的与应用场景

首先,让我们来了解一下SpEL的设计目的和适用场景。SpEL的主要设计目的是为了提供一个灵活而强大的表达式语言,使得Spring框架能够更好地支持动态配置和运行时求值的需求。

对于应用场景来说,SpEL可以被广泛地应用于以下方面:

  • 动态配置:SpEL可以通过表达式来动态地配置Spring中的bean属性、方法参数等,从而实现更加灵活的配置方式。

  • 运行时求值:SpEL可以在运行时对表达式进行求值,从而实现动态计算、判断和决策等功能。

SpEL的核心语法与功能

现在让我们深入研究一下SpEL的核心语法和功能。SpEL的语法结构类似于Java,但也引入了一些新的概念和符号,使得表达式更加灵活和强大。

  • 字面量表达式:SpEL支持各种类型的字面量,包括字符串、数字、布尔值等。例如,'Hello, SpEL!'表示一个字符串字面量。

  • 属性访问:使用.操作符可以访问对象的属性。例如,person.name表示访问person对象的name属性。

  • 方法调用:使用.或者[]操作符可以调用对象的方法。例如,person.getName()表示调用person对象的getName()方法。

  • 运算符:SpEL支持各种运算符,包括算术运算符、关系运算符、逻辑运算符等。例如,1 + 2表示加法运算。

  • 条件表达式:SpEL支持使用三元运算符?:进行条件判断。例如,age >= 18 ? '成年人' : '未成年人'表示根据age的值判断是否成年。

  • 集合操作:SpEL支持对集合进行操作,包括访问集合元素、过滤、投影等。例如,numbers.![#this * 2]表示将numbers集合中的每个元素乘以2。

如何通过SpEL实现动态配置

现在让我们看一个具体的示例,来说明如何通过SpEL实现动态配置。假设我们有一个简单的Java类Person,它有一个名为age的属性。

public class Person {private int age;public int getAge() {return age;}public void setAge(int age) {this.age = age;}
}

我们可以通过SpEL来动态地配置Person对象的age属性。在Spring的配置文件中,使用#{}包裹SpEL表达式。

<bean id="person" class="com.example.Person"><property name="age" value="#{ 18 + 2 }" />
</bean>

上述配置中,SpEL表达式18 + 2会在运行时求值,并将结果赋值给Person对象的age属性。假设我们创建了一个person对象并获取其年龄:

ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
Person person = context.getBean("person", Person.class);
System.out.println(person.getAge());

输出结果为:20

通过这个示例,我们可以看到如何使用SpEL来实现动态配置,通过表达式来计算属性的值,使得配置更加灵活和可变。

总结:BeanFactory与ApplicationContext的精髓

BeanFactoryApplicationContext是Spring容器的核心。BeanFactory提供了高级IoC的配置机制,而ApplicationContext在此基础上添加了更多企业所需的功能,如事件发布、国际化消息支持等。AOP正是ApplicationContext提供的众多高级特性之一,通过它,我们能够以简洁的方式实现应用中的横切关注点。

如何继续深入学习Spring

深入学习Spring的最佳方式是通过实践。建议读者不仅要阅读官方文档,还应该关注Spring的新特性和最佳实践。同时,参与开源项目、阅读源码、编写自己的Spring应用,都是提升自己技术水平的有效途径。

希望这篇博客能够帮助你更好地理解Spring中的AOP特性,以及ApplicationContext的强大功能。记住,学习之路是永无止境的,让我们一起在Spring的世界里不断探索,不断前进。

相关文章:

【Spring源码解读!底层原理进阶】【下】探寻Spring内部:BeanFactory和ApplicationContext实现原理揭秘✨

&#x1f389;&#x1f389;欢迎光临&#x1f389;&#x1f389; &#x1f3c5;我是苏泽&#xff0c;一位对技术充满热情的探索者和分享者。&#x1f680;&#x1f680; &#x1f31f;特别推荐给大家我的最新专栏《Spring 狂野之旅&#xff1a;底层原理高级进阶》 &#x1f680…...

从零开始手写mmo游戏从框架到爆炸(六)— 消息处理工厂

就好像门牌号一样&#xff0c;我们需要把消息路由到对应的楼栋和楼层&#xff0c;总不能像菜鸟一样让大家都来自己找数据吧。 首先这里我们参考了rabbitmq中的topic与tag模型&#xff0c;topic对应类&#xff0c;tag对应方法。 新增一个模块&#xff0c;专门记录路由eternity-…...

Go基础学习笔记-知识点

学习笔记记录了我在学习官方文档过程中记的要点&#xff0c;可以参考学习。 go build *.go 文件 编译 go run *.go 执行 go mod init 生成依赖管理文件 gofmt -w *.go 格式换名称的大小写用来控制方法的可见域主方法及包命名规范 package main //注意package的命名&#xff0…...

jvm几个常见面试题整理

1. Full GC触发机制有如下5种情况。 (1)调用System.gc()时&#xff0c;系统建议执行Full GC&#xff0c;但是不必然执行。(2)老年代空间不足。(3)方法区空间不足。(4)老年代的最大可用连续空间小于历次晋升到老年代对象的平均大小就会进行Full GC。(5)由Eden区、S0(From)区向S…...

ReentrantLock 和 公平锁

ReentrantLock 和 公平锁 一、基本介绍 ReentrantLock(重入锁) 是一个独占式锁&#xff0c;具有和synchronize的监视器锁基本相同的行为和语意。但和synchronized相比&#xff0c;它更加的灵活、强大、增加了轮询、超时、中断等高级功能以及可以创建公平和非公平锁。Reentran…...

使用Postman做API自动化测试

Postman最基本的功能用来重放请求&#xff0c;并且配合良好的response格式化工具。 高级点的用法可以使用Postman生成各个语言的脚本&#xff0c;还可以抓包&#xff0c;认证&#xff0c;传输文件。 仅仅做到这些还不能够满足一个系统的开发&#xff0c;或者说过于琐碎&#…...

入门指南|Chat GPT 的兴起:它如何改变数字营销格局?

随着数字营销的不断发展&#xff0c;支持数字营销的技术也在不断发展。OpenAI 的 ChatGPT 是一项备受关注的突破性工具。凭借其先进的自然语言处理能力&#xff0c;ChatGPT 已被证明是全球营销人员的宝贵资产。在这份入门指南中&#xff0c;我们将探讨Chat GPT对数字营销专家及…...

【C#】.net core 6.0 创建默认Web应用,以及默认结构讲解,适合初学者

欢迎来到《小5讲堂》 大家好&#xff0c;我是全栈小5。 这是《C#》系列文章&#xff0c;每篇文章将以博主理解的角度展开讲解&#xff0c; 特别是针对知识点的概念进行叙说&#xff0c;大部分文章将会对这些概念进行实际例子验证&#xff0c;以此达到加深对知识点的理解和掌握。…...

Linux中的numactl命令指南

假设我们想控制线程如何被分配到处理器核心&#xff0c;或者选择我们想分配数据的位置&#xff0c;那么numactl命令就适合此类任务。在这篇文章中&#xff0c;我们讨论了如何使用numactl命令执行此类操作。 目录&#xff1a; 介绍语法命令总结参考文献 简介 现代处理器采用…...

AD域国产替代方案,助力某金融企业麒麟信创电脑实现“真替真用”

近期收到不少企业客户反馈采购的信创PC电脑用不起来&#xff0c;影响信创改造的进度。例如&#xff0c;某金融企业积极响应国产化信创替代战略&#xff0c;购置了一批麒麟操作系统电脑。分发使用中发现了如下问题&#xff1a; • 当前麒麟操作系统电脑无法做到统一身份认证&…...

抽象springBoot报错

Failed to configure a DataSource: url attribute is not specified and no embedded datasource could be configured. 中文翻译&#xff1a;无法配置DataSource&#xff1a;未指定“url”属性&#xff0c;并且无法配置嵌入数据源。 DataSource 翻译&#xff1a;数据源 得…...

Linux的打包压缩与解压缩---tar、xz、zip、unzip

最近突然用到了许久不用的压缩解压缩命令&#xff0c;真的陌生&#xff0c; 哈哈&#xff0c;记录一下&#xff0c;后续就不用搜索了。 tar的打包 tar -cvf 压缩有的文件名称 需要压缩的文件或文件夹tar -cvf virtualbox.tar virtualbox/ tar -zcvf virtualbox.tar virtualbo…...

在angular12中proxy.conf.json中配置详解

一、proxy.conf.json文件的目录 二、proxy.conf.json文件中的配置 "/xxx/api": {"target": "地址/api","secure": false,"logLevel": "debug","changeOrigin": true,"pathRewrite": {"…...

PyTorch 中音频信号处理库torchaudio的详细介绍

torchaudio 是 PyTorch 深度学习框架的一部分&#xff0c;是 PyTorch 中处理音频信号的库&#xff0c;专门用于处理和分析音频数据。它提供了丰富的音频信号处理工具、特征提取功能以及与深度学习模型结合的接口&#xff0c;使得在 PyTorch 中进行音频相关的机器学习和深度学习…...

OpenAI研究揭示:ChatGPT对生物武器制造影响有限

### OpenAI研究揭示&#xff1a;ChatGPT对生物武器制造影响有限 在最近的一项引人注目的研究中&#xff0c;OpenAI探索了其旗舰人工智能产品GPT-4在辅助制造生物武器方面的潜力。尽管公众对人工智能可能带来的潜在风险表示担忧&#xff0c;但OpenAI的发现却意味着这种担忧可能…...

IntelliJ IDEA 2023.3发布,AI 助手出世,新特性杀麻了!!

目录 关键亮点 对 Java 21 功能的完全支持 调试器中的 Run to Cursor&#xff08;运行到光标)嵌入选项 带有编辑操作的浮动工具栏 用户体验优化 Default&#xff08;默认&#xff09;工具窗口布局选项 默认颜色编码编辑器标签页 适用于 macOS 的新产品图标 Speed Sear…...

async 与 await(JavaScript)

目录捏 前言一、async二、await三、使用方法总结 前言 async / await 是 ES2017(ES8) 提出的基于 Promise 解决异步的最终方案。上一篇文章介绍了 回调地狱 与 Promise&#xff08;JavaScript&#xff09;&#xff0c;因为 Promise 的编程模型依然充斥着大量的 then 方法&#…...

GPT-1, GPT-2, GPT-3, GPT-3.5, GPT-4论文内容解读

目录 1 ChatGPT概述1.1 what is chatGPT1.2 How does ChatGPT work1.3 The applications of ChatGPT1.3 The limitations of ChatGPT 2 算法原理2.1 GPT-12.1.1 Unsupervised pre-training2.1.2 Supervised fine-tuning2.1.3 语料2.1.4 分析 2.2 GPT-22.3 GPT-32.4 InstructGPT…...

第62讲商品搜索动态实现以及性能优化

商品搜索后端动态获取数据 后端动态获取数据&#xff1a; /*** 商品搜索* param q* return*/GetMapping("/search")public R search(String q){List<Product> productList productService.list(new QueryWrapper<Product>().like("name", q)…...

我的PyTorch模型比内存还大,怎么训练呀?

原文&#xff1a;我的PyTorch模型比内存还大&#xff0c;怎么训练呀&#xff1f; - 知乎 看了一篇比较老&#xff08;21年4月文章&#xff09;的不大可能训练优化方案&#xff0c;保存起来以后研究一下。 随着深度学习的飞速发展&#xff0c;模型越来越臃肿&#xff0c;哦不&a…...

idea大量爆红问题解决

问题描述 在学习和工作中&#xff0c;idea是程序员不可缺少的一个工具&#xff0c;但是突然在有些时候就会出现大量爆红的问题&#xff0c;发现无法跳转&#xff0c;无论是关机重启或者是替换root都无法解决 就是如上所展示的问题&#xff0c;但是程序依然可以启动。 问题解决…...

工业安全零事故的智能守护者:一体化AI智能安防平台

前言&#xff1a; 通过AI视觉技术&#xff0c;为船厂提供全面的安全监控解决方案&#xff0c;涵盖交通违规检测、起重机轨道安全、非法入侵检测、盗窃防范、安全规范执行监控等多个方面&#xff0c;能够实现对应负责人反馈机制&#xff0c;并最终实现数据的统计报表。提升船厂…...

iPhone密码忘记了办?iPhoneUnlocker,iPhone解锁工具Aiseesoft iPhone Unlocker 高级注册版​分享

平时用 iPhone 的时候&#xff0c;难免会碰到解锁的麻烦事。比如密码忘了、人脸识别 / 指纹识别突然不灵&#xff0c;或者买了二手 iPhone 却被原来的 iCloud 账号锁住&#xff0c;这时候就需要靠谱的解锁工具来帮忙了。Aiseesoft iPhone Unlocker 就是专门解决这些问题的软件&…...

Android15默认授权浮窗权限

我们经常有那种需求&#xff0c;客户需要定制的apk集成在ROM中&#xff0c;并且默认授予其【显示在其他应用的上层】权限&#xff0c;也就是我们常说的浮窗权限&#xff0c;那么我们就可以通过以下方法在wms、ams等系统服务的systemReady()方法中调用即可实现预置应用默认授权浮…...

什么?连接服务器也能可视化显示界面?:基于X11 Forwarding + CentOS + MobaXterm实战指南

文章目录 什么是X11?环境准备实战步骤1️⃣ 服务器端配置(CentOS)2️⃣ 客户端配置(MobaXterm)3️⃣ 验证X11 Forwarding4️⃣ 运行自定义GUI程序(Python示例)5️⃣ 成功效果![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/55aefaea8a9f477e86d065227851fe3d.pn…...

纯 Java 项目(非 SpringBoot)集成 Mybatis-Plus 和 Mybatis-Plus-Join

纯 Java 项目&#xff08;非 SpringBoot&#xff09;集成 Mybatis-Plus 和 Mybatis-Plus-Join 1、依赖1.1、依赖版本1.2、pom.xml 2、代码2.1、SqlSession 构造器2.2、MybatisPlus代码生成器2.3、获取 config.yml 配置2.3.1、config.yml2.3.2、项目配置类 2.4、ftl 模板2.4.1、…...

QT开发技术【ffmpeg + QAudioOutput】音乐播放器

一、 介绍 使用ffmpeg 4.2.2 在数字化浪潮席卷全球的当下&#xff0c;音视频内容犹如璀璨繁星&#xff0c;点亮了人们的生活与工作。从短视频平台上令人捧腹的搞笑视频&#xff0c;到在线课堂中知识渊博的专家授课&#xff0c;再到影视平台上扣人心弦的高清大片&#xff0c;音…...

针对药品仓库的效期管理问题,如何利用WMS系统“破局”

案例&#xff1a; 某医药分销企业&#xff0c;主要经营各类药品的批发与零售。由于药品的特殊性&#xff0c;效期管理至关重要&#xff0c;但该企业一直面临效期问题的困扰。在未使用WMS系统之前&#xff0c;其药品入库、存储、出库等环节的效期管理主要依赖人工记录与检查。库…...

何谓AI编程【02】AI编程官网以优雅草星云智控为例建设实践-完善顶部-建立各项子页-调整排版-优雅草卓伊凡

何谓AI编程【02】AI编程官网以优雅草星云智控为例建设实践-完善顶部-建立各项子页-调整排版-优雅草卓伊凡 背景 我们以建设星云智控官网来做AI编程实践&#xff0c;很多人以为AI已经强大到不需要程序员了&#xff0c;其实不是&#xff0c;AI更加需要程序员&#xff0c;普通人…...

React父子组件通信:Props怎么用?如何从父组件向子组件传递数据?

系列回顾&#xff1a; 在上一篇《React核心概念&#xff1a;State是什么&#xff1f;》中&#xff0c;我们学习了如何使用useState让一个组件拥有自己的内部数据&#xff08;State&#xff09;&#xff0c;并通过一个计数器案例&#xff0c;实现了组件的自我更新。这很棒&#…...