Spring实例化源码解析之MessageSource(七)

news2024/11/24 10:47:25

前言

在阅读完 registerBeanPostProcessors 源码之后, 下一步就进入到 initMessageSource,这一步主要作用是初始化国际化文件。

源码分析

这段源码是一个Java方法,用于初始化消息源(MessageSource)。在Spring框架中,消息源用于提供本地化消息,例如错误消息或用户界面文本,以便支持国际化和本地化。

让我们逐行分析这段源码:

  1. 获取当前对象的Bean工厂(BeanFactory)。
  2. 检查Bean工厂中是否包含名为"MESSAGE_SOURCE_BEAN_NAME"的本地消息源Bean。这个常量可能是在其他地方定义的消息源Bean的名称。
  3. 如果存在该本地消息源Bean,则从Bean工厂中获取该Bean,并将其设置为当前对象的消息源(messageSource)属性。
  4. 如果当前对象有一个父级对象(parent)且消息源实现了"HierarchicalMessageSource"接口,则将父级对象的消息源设置为当前消息源的父级消息源。
  5. 如果消息源Bean是空的,即没有找到名为"MESSAGE_SOURCE_BEAN_NAME"的本地消息源Bean,则创建一个新的DelegatingMessageSource对象作为空消息源,并将父级消息源设置为当前对象的父级消息源。
  6. 将消息源Bean注册到Bean工厂中。
  7. 日志记录,如果启用了跟踪级别的日志,将打印消息源的使用情况。

这段源码的作用是在Spring应用程序中初始化消息源,以便支持国际化和本地化的消息处理。具体的消息源实现可能会根据应用程序的需求而有所不同。

protected void initMessageSource() {
		ConfigurableListableBeanFactory beanFactory = getBeanFactory();
		if (beanFactory.containsLocalBean(MESSAGE_SOURCE_BEAN_NAME)) {
			this.messageSource = beanFactory.getBean(MESSAGE_SOURCE_BEAN_NAME, MessageSource.class);
			// Make MessageSource aware of parent MessageSource.
			if (this.parent != null && this.messageSource instanceof HierarchicalMessageSource) {
				HierarchicalMessageSource hms = (HierarchicalMessageSource) this.messageSource;
				if (hms.getParentMessageSource() == null) {
					// Only set parent context as parent MessageSource if no parent MessageSource
					// registered already.
					hms.setParentMessageSource(getInternalParentMessageSource());
				}
			}
			if (logger.isTraceEnabled()) {
				logger.trace("Using MessageSource [" + this.messageSource + "]");
			}
		}
		else {
			// Use empty MessageSource to be able to accept getMessage calls.
			DelegatingMessageSource dms = new DelegatingMessageSource();
			dms.setParentMessageSource(getInternalParentMessageSource());
			this.messageSource = dms;
			// 注册一个messageSource
			beanFactory.registerSingleton(MESSAGE_SOURCE_BEAN_NAME, this.messageSource);
			if (logger.isTraceEnabled()) {
				logger.trace("No '" + MESSAGE_SOURCE_BEAN_NAME + "' bean, using [" + this.messageSource + "]");
			}
		}
	}

官网使用简述

MessageSource

MessageSource在官网中的描述如下图所示:

在这里插入图片描述

ApplicationContext接口扩展了一个名为MessageSource的接口,因此提供了国际化(“i18n”)功能。Spring还提供了HierarchicalMessageSource接口,它可以按层次结构解析消息。这些接口共同构成了Spring实现消息解析的基础。这些接口定义的方法包括:

  • String getMessage(String code, Object[] args, String default, Locale loc):从MessageSource中检索消息的基本方法。当找不到指定区域设置的消息时,将使用默认消息。传入的任何参数都将成为替换值,使用标准库提供的MessageFormat功能。

  • String getMessage(String code, Object[] args, Locale loc):与前一个方法基本相同,但有一个区别:无法指定默认消息。如果找不到消息,将抛出NoSuchMessageException异常。

  • String getMessage(MessageSourceResolvable resolvable, Locale locale):前面的方法中使用的所有属性也都包装在一个名为MessageSourceResolvable的类中,您可以将其与此方法一起使用。

当加载一个ApplicationContext时,它会自动搜索在上下文中定义的MessageSource bean。该bean的名称必须为messageSource。如果找到这样的bean,所有对前面方法的调用将委托给该消息源。如果找不到消息源,ApplicationContext会尝试查找一个父级上下文,并查找具有相同名称的bean。如果找到,则使用该bean作为MessageSource。如果ApplicationContext找不到任何消息源,将实例化一个空的DelegatingMessageSource以接受上述定义的方法的调用。

Spring提供了三种MessageSource实现,分别是ResourceBundleMessageSource、ReloadableResourceBundleMessageSource和StaticMessageSource。它们都实现了HierarchicalMessageSource以实现嵌套消息。StaticMessageSource很少使用,但提供了以编程方式向源中添加消息的方法。下面是一个示例,展示了ResourceBundleMessageSource的用法:

<beans>
	<bean id="messageSource"
			class="org.springframework.context.support.ResourceBundleMessageSource">
		<property name="basenames">
			<list>
				<value>format</value>
				<value>exceptions</value>
				<value>windows</value>
			</list>
		</property>
	</bean>
</beans>

该示例假设您的类路径中有三个资源包,分别称为format、exceptions和windows。通过ResourceBundle对象处理任何解析消息的请求遵循JDK标准的方式。为了示例的目的,假设上述两个资源包文件的内容如下所示:

# in format.properties
message=Alligators rock!
# in exceptions.properties
argument.required=The {0} argument is required.

下面的示例展示了运行MessageSource功能的程序。请记住,所有的ApplicationContext实现也是MessageSource实现,因此可以将其转换为MessageSource接口。

public static void main(String[] args) {
	MessageSource resources = new ClassPathXmlApplicationContext("beans.xml");
	String message = resources.getMessage("message", null, "Default", Locale.ENGLISH);
	System.out.println(message);
}

结果如下:

Alligators rock!

总结一下,MessageSource在名为beans.xml的文件中进行了定义,该文件位于类路径的根目录下。messageSource bean定义通过其basenames属性引用了多个资源包。在basenames属性的列表中传递的三个文件作为文件存在于类路径的根目录下,分别为format.properties、exceptions.properties和windows.properties。

下面的示例展示了传递给消息查找的参数。这些参数将被转换为String对象,并插入到查找消息中的占位符中。

<beans>

	<!-- this MessageSource is being used in a web application -->
	<bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">
		<property name="basename" value="exceptions"/>
	</bean>

	<!-- lets inject the above MessageSource into this POJO -->
	<bean id="example" class="com.something.Example">
		<property name="messages" ref="messageSource"/>
	</bean>

</beans>
public class Example {

	private MessageSource messages;

	public void setMessages(MessageSource messages) {
		this.messages = messages;
	}

	public void execute() {
		String message = this.messages.getMessage("argument.required",
			new Object [] {"userDao"}, "Required", Locale.ENGLISH);
		System.out.println(message);
	}
}

调用execute()方法后的输出结果如下所示:

The userDao argument is required.

关于国际化(“i18n”),Spring的各种MessageSource实现遵循与标准JDK ResourceBundle相同的区域设置解析和回退规则。简而言之,继续使用先前定义的messageSource示例,如果您想针对英国(en-GB)区域设置解析消息,您将分别创建名为format_en_GB.properties、exceptions_en_GB.properties和windows_en_GB.properties的文件。

通常,区域设置的解析由应用程序的周围环境管理。在下面的示例中,手动指定了用于解析(英国)消息的区域设置:

# in exceptions_en_GB.properties
argument.required=Ebagum lad, the ''{0}'' argument is required, I say, required.
public static void main(final String[] args) {
	MessageSource resources = new ClassPathXmlApplicationContext("beans.xml");
	String message = resources.getMessage("argument.required",
		new Object [] {"userDao"}, "Required", Locale.UK);
	System.out.println(message);
}

运行上述程序后的输出结果如下所示:

Ebagum lad, the 'userDao' argument is required, I say, required.

您还可以使用MessageSourceAware接口来获取对已定义的任何MessageSource的引用。在实现了MessageSourceAware接口的ApplicationContext中定义的任何bean在创建和配置时都会被注入应用程序上下文的MessageSource。

注意

由于Spring的MessageSource基于Java的ResourceBundle,它不会合并具有相同基本名称的资源包,而只会使用找到的第一个资源包。后续具有相同基本名称的消息资源包将被忽略。

作为ResourceBundleMessageSource的替代方案,Spring提供了ReloadableResourceBundleMessageSource类。这个变种支持与标准的基于JDK的ResourceBundleMessageSource实现相同的资源包文件格式,但比它更灵活。特别是,它允许从任何Spring资源位置读取文件(不仅限于类路径),并支持在热加载资源包属性文件时高效地进行缓存。有关详细信息,请参阅ReloadableResourceBundleMessageSource的Java文档。

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

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

相关文章

万字详解HTTP协议面试必备技能

目录 一、HTTP 是什么 二、理解 "应用层协议" 2.1理解 HTTP 协议的工作过程 2.2HTTP 协议格式 2.3抓包工具的使用 2.4抓包工具的原理 2.5抓包结果 2.5.1HTTP请求 2.5.2HTTP响应 2.6协议格式总结 三、HTTP 请求 (Request) 3.1认识 URL 3.1.1URL 基本格式 …

Jmeter 多实例压测

Apache JMeter 是一个开源的 Java 应用程序&#xff0c;用于性能测试和负载测试。它最初是为测试 Web 应用程序而创建的&#xff0c;但现在已广泛用于测试各种不同类型的应用程序&#xff0c;包括数据库、消息队列、FTP 服务器等。JMeter 提供了丰富的功能&#xff0c;使您能够…

行内元素文字背景被截断的问题,如何进行修改?

1.问题如图所示 这里背景是被截断的&#xff0c;有什么css样式可以修改它呢&#xff1f; 效果实现如图&#xff1a; 不一样的地方在于这里的截断位置是引用了开头和结尾的位置。 如何实现&#xff1f; <!DOCTYPE html> <html lang"en"> <head><…

终于找到了!Jenkins最全最详细入门指南

目录 一、介绍 二、功能 三、搭建Jenkins目的 四、安装 五、Jenkins的三大概念 六、创建job & 配置git 七、构建触发器&#xff08;build triggers&#xff09; 八、运行python脚本 九、测试报告展示 十、配置邮件并发送 最后 一、介绍 Jenkins是开源的,使用Java编…

Linux系统部署PostgreSQL 单机数据库

安装方式 1 安装包方式 &#xff08;Packages and Installers&#xff09; 支持的操作系统包括 liunxMacosWindowsBSDSolaris 2 源码安装 &#xff08;Source code&#xff09; 下载源码包 通过下载地址PostgreSQL: File Browser 可以看到有各个版本的源码目录 选择13.1…

二维离散傅里叶变换的实现

二维离散傅里叶变换的实现 1.使用Python包实现2.使用c实现2.1 FFTW库安装2.2 结果比较 参考文献 1.使用Python包实现 import numpy as np import matplotlib.pyplot as plt anp.array([0, 2, 4, 1,6, 1, 3, 2,5]).reshape(3,3) fnp.fft.fft2(a) fshiftnp.fft.fftshift(f) mag…

CSS圆角大杀器,使用滤镜构建圆角及波浪效果

目录 1&#xff0c;border-radius实现圆角2&#xff0c;filter: contrast() 配合 filter: blur() 实现圆角3&#xff0c;使用 filter: contrast() 配合 filter: blur() 实现波浪效果 1&#xff0c;border-radius实现圆角 通常我们加个 border-radius就可实现一个div盒子的圆角…

分页查询(关键词: limit)

MySQL从小白到总裁完整教程目录:https://blog.csdn.net/weixin_67859959/article/details/129334507?spm1001.2014.3001.5502 比如现在有一张表emp有15条数据 我想每页只显示5条数据,分3页,这样看起来简捷一些,我该怎么实现呢 语法格式: select */列名 from 表名 limit 初…

CMAKE使用记录

CMAKE使用记录 CMake简化了针对同一项目的不同平台、不同编译器的构建过程和编译过程&#xff0c;能够管理各种规模的项目。 CMAKE命令记录 cmake命令说明 语法&#xff1a; # cmake构建项目的编译系统 Generate a Project Buildsystem > cmake [<options>] -B &…

85.最大矩形

单调栈&#xff0c;时间复杂度o(mn)&#xff0c;空间复杂度o(mn) class Solution { public:int maximalRectangle(vector<vector<char>>& matrix) {int mmatrix.size();if(m0){return 0;}int nmatrix[0].size();//记录矩阵中每个元素左边连续1的数量vector<…

如何开发一款高效便捷的搬家服务小程序

随着互联网的发展&#xff0c;小程序已成为各行各业重要的业务推广和用户服务平台。对于搬家行业而言&#xff0c;开发一款高效便捷的搬家服务小程序具有巨大的市场潜力。本文将为您详细介绍如何开发一款这样的搬家服务小程序。 一、进入乔拓云网后台 在开始制作搬家服务小程序…

番外项目---Vim编辑器

Task01: 1.在/tmp目录下建立一个名为mytest的目录&#xff0c;进入mytest目录当中; 2.将/etc/man_db.conf复制到上述目录下面&#xff0c;使用vim打开目录下的man_db.conf文件; 3.在vim中设定行号&#xff0c;移动到第58行&#xff0c;向右移动15个字符&#xff0c;请问你看到…

文件丢失怎么找回?收藏好这3个方法!

“我真的要哭了&#xff0c;不小心把一些很重要的文件弄丢了&#xff0c;现在不知道该怎么办了&#xff0c;有没有什么方法可以把这些文件找回来呀&#xff1f;大家快帮帮我吧&#xff01;” 在日常办公中&#xff0c;很多用户都会习惯性的把一些重要的文件和数据保存在电脑上。…

UE4游戏客户端开发进阶学习指南

前言 两年多前写过一篇入门指南&#xff0c;教大家在短时间内快速入门UE4的使用&#xff0c;在知乎被很多人收藏了。如今鸡佬使用UE快三年了&#xff0c;是时候更新一下进阶版本的学习指南。本文对于读者的要求&#xff1a; 有一定的C基础已经入门UE&#xff0c;能够用蓝图和…

AD 域控使用回收站批量还原用户

一、Read me. 测试版本winserver 2019&#xff0c;其余版本请查阅文档或者实际操作尝试。 前提需要预先开启回收站功能&#xff01;&#xff01;&#xff01;&#xff01; 没有开启可以点&#xff0c;开启后则变灰色。 如果是人为操作并且没有开启这个功能&#xff0c;那么不…

【算法训练-数组 四】【数组合并】:合并两个有序数组

废话不多说&#xff0c;喊一句号子鼓励自己&#xff1a;程序员永不失业&#xff0c;程序员走向架构&#xff01;本篇Blog的主题是【数组组合】&#xff0c;使用【数组】这个基本的数据结构来实现&#xff0c;这个高频题的站点是&#xff1a;CodeTop&#xff0c;筛选条件为&…

【小黑送书—第三期】>>《深入浅出SSD》

近年来国家大力支持半导体行业&#xff0c;鼓励自主创新&#xff0c;中国SSD技术和产业良性发展&#xff0c;产业链在不断完善&#xff0c;与国际厂商的差距逐渐缩小。但从行业发展趋势来看&#xff0c;SSD相关技术仍有大幅进步的空间&#xff0c;SSD相关技术也确实在不断前进。…

localhost和127.0.0.1都可以访问项目,但是本地的外网IP不能访问

使用localhost和127.0.0.1都可以访问接口&#xff0c;比如&#xff1a; http://localhost:8080/zhgl/login/login-fy-list或者 http://127.0.0.1:8080/zhgl/login/login-fy-list返回json {"_code":10000,"_msg":"Success","_data":…

数据结构与算法-循环链表、双向链表

我们这里接着上一篇单链表继续往下深入学习循环链表、双向链表。 链表 &#x1f388;3.循环链表&#x1f52d;3.1循环链表的概念&#x1f52d;3.2循环链表的基本操作&#x1f50e;3.2.1创建空表&#x1f50e;3.2.2插入操作&#x1f50e;3.2.3删除操作 &#x1f388;4.双向链表&…

图的存储-链式前向星

链式前向星 链式前向星是民间OI选手发明的数据结构。用另一个词解释它就是&#xff1a;用数组模拟的邻接链表。最核心的思想就是用数组模拟链表。 &#xff08;1&#xff09;前向星 前向星就是边的集合。一个图&#xff0c;只要将它的所有边存储起来&#xff0c;就能知道它的…