欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

SpringBoot2.x升级踩坑--新增Configuration property name限制

程序员文章站 2023-11-14 16:45:04
源码解析,SpringBoot2.x升级踩坑,新增Configuration property name限制。 ......

最近公司项目在做springboot的升级,在升级过程中遇到了一些问题,简单记录一下,做个分享。另外,本文中的程序只为示例代码,并非公司生产环境代码。

遇到什么问题

从springboot1.x升级到springboot2.x之后,解决完编译异常,运行程序,在程序启动时报错:

SpringBoot2.x升级踩坑--新增Configuration property name限制

报错信息就已经很直白的告诉了我们错误原因:

配置属性名称“com_shen”无效

无效字符: '_', 原因:规范名称应为kebab-case(用'-'分隔),小写字母数字字符,并且必须以字母开头

怎么解决

经过排查,是因为在application.properties文件中有如下一个配置项:

com_shen.name=xiaohei

对应java程序代码:

@getter
@setter
@configurationproperties(prefix = "com_shen")
public class service {
    private string name;
}

结合报错日志,我们可以很容易的解决这个问题,去掉配置项中的_,将配置项name修改为com.shen.name即可。

源码解析

你以为文章写到这里就结束了吗?其实并没有。hhhhhh,通过这个问题,我们来看一下springboot2.x的内部源码。什么,你不知道该从哪里入手来看这个源码,没关系,我们一步一步来。

点开@configurationproperties源码,

SpringBoot2.x升级踩坑--新增Configuration property name限制

在spring中,大量的功能都是通过beanpostprocessor来实现的。而且,spring中的源码注释写的非常的仔细。通过源码注释我们可以猜到可能是configurationpropertiesbindingpostprocessor这个类在负责@configurationproperties注解的背后支持。

点开configurationpropertiesbindingpostprocessor类源码,发现在该类中override了beanpostprocessorpostprocessbeforeinitialization方法:
SpringBoot2.x升级踩坑--新增Configuration property name限制
在这个方法中,调用了bind(bean, beanname, annotation);方法。这个方法名叫"绑定",方法中传入了bean、beanname和annotation的信息,经验告诉我这个方法大概率就是在负责解析@configurationproperties,进行属性绑定。

于是,在这里打一个条件断点,debug运行项目:

SpringBoot2.x升级踩坑--新增Configuration property name限制

通过debug发现的确是这个方法在进行属性绑定。而且底层调用了org.springframework.boot.context.properties.bind.binder#bind(string, bindable<t>, bindhandler) 方法:

SpringBoot2.x升级踩坑--新增Configuration property name限制

在这个bind方法中,又调用了另一个方法bind(configurationpropertyname.of(name), target, handler);,而且通过name生成了configurationpropertyname对象configurationpropertyname.of(name),通过方法名我们可以猜测,这个方法可能是在负责解析configuration property name,项目启动的报错信息很有可能是这个方法中抛出的。点开源码:

SpringBoot2.x升级踩坑--新增Configuration property name限制

发现在这个方法中,调用了invalidconfigurationpropertynameexception.throwifhasinvalidchars(name,elementvalidator.getinvalidchars(elementvalue));。spring代码命名真的是太优雅了,虽然名称很长,但是让源码阅读者一看就能明白这个方法在做什么。

SpringBoot2.x升级踩坑--新增Configuration property name限制

SpringBoot2.x升级踩坑--新增Configuration property name限制

通过源码,我们可以看到,在springboot中对configuration property name中的字符进行了有效性的判断,判断规则如上图所示。

elementvalidator类是configurationpropertyname的一个内部类。configurationpropertyname是springboot2.0新增的一个类,让我们一起来阅读一下类中注释,了解一下这个类:

SpringBoot2.x升级踩坑--新增Configuration property name限制

机器翻译结果如下:

由点分隔的元素组成的配置属性名称。 用户创建的名称可以包含字符“ a-z”,“ 0-9”)和“-”,它们必须为小写字母,并且必须以字母数字字符开头。 “-”仅用于格式化,即“ foo-bar”和“ foobar”被认为是等效的。
“ [”和“]”字符可用于表示关联索引(即map键或collection索引。索引名称不受限制,并且区分大小写。

以下是一些典型示例:

spring.main.banner-mode
server.hosts [0]。名称
日志[org.springboot] .level

使用@value

我们知道,springboot中除了可以使用@configurationproperties之外,还可以使用@value

demo程序如下:

@getter
@setter
@component
public class service {

    @value("${com_shen.name}")
    private string name;
}

application.properties文件:

com_shen.name=xiaohei

在这种情况下,项目依旧启动成功了,而且成功的获取到了com_shen.name的属性值。也就是说,@value注解中并没有表达式做限制。

拓展阅读

property binding in spring boot 2.0 : https://spring.io/blog/2018/03/28/property-binding-in-spring-boot-2-0


欢迎关注公众号,大家一起学习成长。

SpringBoot2.x升级踩坑--新增Configuration property name限制