Spring boot 2.1.3 从 2.0.6 更新导致 util:map 的 BeanDefinitionParsingException

Posted

技术标签:

【中文标题】Spring boot 2.1.3 从 2.0.6 更新导致 util:map 的 BeanDefinitionParsingException【英文标题】:Spring boot 2.1.3 update from 2.0.6 causes an BeanDefinitionParsingException for util:map 【发布时间】:2019-09-22 02:35:21 【问题描述】:

我在应用程序上下文 xml 中有以下映射 bean 定义,并在控制器中使用了导致 BeanDefinitionParsingException 用于 spring boot 2.1.3 升级的映射。它在2.0.6 版本 中运行良好。

有人知道如何解决这个问题吗?

在应用程序属性中定义“spring.main.allow-bean-definition-overriding=true”并不能解决问题。

@SpringBootApplication
@PropertySource("classpath:app.properties")
public class Application extends SpringBootServletInitializer 


    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder application) 
        return application.sources(Application.class);
    

    public static void main(String[] args) throws Exception // NOSONAR
        SpringApplication.run(Application.class, args);
    



@Configuration
public class ApplicationConfig 

    @Configuration
    @ImportResource("classpath*:applicationContext.xml")    
    public static class XmlImportingConfiguration 
    



app.properties
#Spring Boot
server.contextPath=/myapp
server.servlet.context-path=/myapp
spring.application.name=myapp
server.tomcat.max-threads=200
server.port=901
server.error.whitelabel.enabled=false

logging.level.org.springframework.web: INFO
logging.level.org.springframework: INFO
logging.level.com.wellsfargo: INFO
server.tomcat.accessLogEnabled=false
logging.config=config/log4j2.xml

spring.view.prefix: /WEB-INF/jsp/
spring.view.suffix: .jsp

applicationContext.xml 
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
    xmlns:task="http://www.springframework.org/schema/task" xmlns:util="http://www.springframework.org/schema/util"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
       http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-3.0.xsd
       http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd
       http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">

        <util:map id="lookup">
            <entry key="60" value="1 hour"></entry>
            <entry key="480" value="8 hours"></entry>
            <entry key="1440" value="24 hours"></entry>
            <entry key="2880" value="2 days"></entry>
        </util:map>
</beans>

@Controller
@RequestMapping("/")
public class MyController
    @Resource(name="lookup")
    private Map<String,String> lookup;


错误:

org.springframework.beans.factory.parsing.BeanDefinitionParsingException: 配置问题:名称为 'lookup' 的 bean 定义无效 在 null 中定义:无法注册 bean 定义 [通用 bean:类 [org.springframework.beans.factory.config.MapFactoryBean];范围=; 摘要=假;懒惰初始化=假;自动线模式=0;依赖检查=0; 自动接线候选=真;主要=假;工厂BeanName=空; 工厂方法名=空;初始化方法名=空;销毁方法名=空] 对于 bean 'lookup':已经有 [Generic bean: class [org.springframework.beans.factory.config.MapFactoryBean];范围=; 摘要=假;懒惰初始化=假;自动线模式=0;依赖检查=0; 自动接线候选=真;主要=假;工厂BeanName=空; 工厂方法名=空;初始化方法名=空;销毁方法名=空] 绑定。

【问题讨论】:

你在哪里定义了地图,它是否包含在配置中 在applicationContext.xml中定义 您可以添加您的应用程序上下文 xml 吗? @skumar 我添加了一个基本示例github.com/DarrenForsythe/resource-bean-override 我可以重新创建问题的唯一方法是拥有两个名为“lookup”的 bean,这让我认为还有另一个隐藏在某个地方名称查找 - 注意 bean 定义与 bean 的名称而不是它们的类型有关,因此如果在其他任何地方定义了另一个称为“查找”的名称,则会出错 @skumar 正如 Darren 指出的那样,在其他地方定义了另一个查找手动清理您的构建文件夹,这也可能是因为 IDE 问题 【参考方案1】:

我有解决这个问题的方法。基本上将地图从 applicationContext.xml 移动到应用程序属性并使用 @Value 检索,如下所示。

app.properties
lookup='60':'Last 1 hour','480':'Last 8 hours','1440':'Last 24 hours','2880':'Last 2 days'

ApplicationProperties.java
    @Value("#$lookup")
    private Map<String,String> lookupTimeinterval;

【讨论】:

您可能还想考虑@ConfigurationProperties【参考方案2】:

这可能不是您想要的,但为什么不使用 Java Config 替换 XML。您不应该启用 bean 覆盖,因为它会使调试 Spring IoC 启动问题变得非常非常困难。

@Configuration
public class ApplicationConfig 

    @Bean
    public Map<String, String> lookup() 
      return Map.of(
            "60", "1 hour", 
            "480", "8 hour", 
            "1440", "24 hours", 
            "2880", "2 days"
      );
    


【讨论】:

我不想硬编码代码中的常量。无论如何,我想出了下面提到的不同解决方案。 @skumar 也许您的现实生活示例更复杂,但示例常量没有意义,可以使用Duration 类或简单算术计算。【参考方案3】:

您也可以使用“yaml”文件来代替“application.properties”文件。

Yaml 支持属性中的键值。

应用程序.yaml

myVales:
  60: "1 hour" 
  480: "8 hour" 
  1440: "24 hours" 
  2880: "2 days"

MyConfig.class

@Configuration
@ConfigurationProperties
public class MyConfig 

    private Map<String, String> myValues;

    //getters


【讨论】:

以上是关于Spring boot 2.1.3 从 2.0.6 更新导致 util:map 的 BeanDefinitionParsingException的主要内容,如果未能解决你的问题,请参考以下文章

使用 JUnit 5 的 spring-boot-starter-test

如何使我的Spring Boot微服务使用HTTPS运行?

滴滴将裁员15%涉及员工超2000人;Spring Boot 2.1.3 发布……

第三章spring boot原理分析

Spring boot 开发WebService遇到的问题之一

Spring Boot 2 Actuator Starter 中的 Nullpointer w。 Tomcat指标