【问题标题】:dispatcherServlet bean collision issuedispatcherServlet bean 冲突问题
【发布时间】:2020-08-30 13:07:08
【问题描述】:

我正在尝试运行一些 Spring Boot 应用程序,但我遇到了以下问题:

    :: Built with Spring Boot :: 2.3.1.RELEASE                                                                                                                                                                        
                                                                                                                                                                                                                  
                                                                                                                                                                                                                  
2020-08-30 17:43:17.953 GMT+05:30  INFO rid=NA cid=NA 21756 --- [           main] o.s.s.petclinic.PetClinicApplication     : Starting PetClinicApplication v2.3.1.BUILD-SNAPSHOT on saasas-WX-3 with PID 21756 (C:
\work\upstream\fault-tolerance-demo\target\spring-petclinic-2.3.1.BUILD-SNAPSHOT.jar started by krsoni in C:\work\upstream\fault-tolerance-demo)                                                                  
2020-08-30 17:43:17.959 GMT+05:30  INFO rid=NA cid=NA 21756 --- [           main] o.s.s.petclinic.PetClinicApplication     : No active profile set, falling back to default profiles: default                     
2020-08-30 17:43:19.799 GMT+05:30  WARN rid=NA cid=NA 21756 --- [           main] ConfigServletWebServerApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org
.springframework.beans.factory.support.BeanDefinitionOverrideException: Invalid bean definition with name 'dispatcherServlet' defined in class path resource [com/mycompany/asr/autoconfigure/asr/ASRAutoConfiguration
.class]: Cannot register bean definition [Root bean: class [null]; scope=; abstract=false; lazyInit=null; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=com.mycompany.asr.
autoconfigure.asr.ASRAutoConfiguration; factoryMethodName=getDispatcherServlet; initMethodName=null; destroyMethodName=(inferred); defined in class path resource [com/mycompany/asr/autoconfigure/asr/ASRAutoConfigur
ation.class]] for bean 'dispatcherServlet': There is already [Root bean: class [null]; scope=; abstract=false; lazyInit=null; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBea
nName=org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration$DispatcherServletConfiguration; factoryMethodName=dispatcherServlet; initMethodName=null; destroyMethodName=(inferred)
; defined in class path resource [org/springframework/boot/autoconfigure/web/servlet/DispatcherServletAutoConfiguration$DispatcherServletConfiguration.class]] bound.                                             
2020-08-30 17:43:19.811 GMT+05:30  INFO rid=NA cid=NA 21756 --- [           main] ConditionEvaluationReportLoggingListener :                                                                                      
                                                                                                                                                                                                                  
Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled.                                                                                                 
2020-08-30 17:43:19.813 GMT+05:30 ERROR rid=NA cid=NA 21756 --- [           main] o.s.b.d.LoggingFailureAnalysisReporter   :                                                                                      
                                                                                                                                                                                                                  
***************************                                                                                                                                                                                       
APPLICATION FAILED TO START                                                                                                                                                                                       
***************************                                                                                                                                                                                       
                                                                                                                                                                                                                  
Description:                                                                                                                                                                                                      
                                                                                                                                                                                                                  
The bean 'dispatcherServlet', defined in class path resource [com/mycompany/asr/autoconfigure/asr/ASRAutoConfiguration.class], could not be registered. A bean with that name has already been defined in class path r
esource [org/springframework/boot/autoconfigure/web/servlet/DispatcherServletAutoConfiguration$DispatcherServletConfiguration.class] and overriding is disabled.                                                  
                                                                                                                                                                                                                  
Action:                                                                                                                                                                                                           
                                                                                                                                                                                                                  
Consider renaming one of the beans or enabling overriding by setting spring.main.allow-bean-definition-overriding=true          

这个 bean 定义在下面的类。而且是第三方jar,不能修改:

@Configuration
@PropertySource("asr.properties")
@EnableConfigurationProperties(AsrProperties.class)
public class ASRAutoConfiguration {

    @Autowired
    AsrProperties asrProperties;

    @Bean
    public EmbeddedServletContainerCustomizer getEmbeddedServletContainerCustomizer() {
        // this property is accessed from many Contexts, so setting in system is the easiest
        System.setProperty("org.apache.catalina.STRICT_SERVLET_COMPLIANCE", "true");

        // configure Tomcat based on properties
        AsrTomcatProperties asrTomcatProperties = new AsrTomcatProperties();
        asrTomcatProperties.setConnectionTimeout(asrProperties.getServer().getConnectionTimeout());
        asrTomcatProperties.setMaxSwallowSize(asrProperties.getServer().getMaxSwallowSize());

        return new AsrEmbeddedTomcatCustomizer(asrTomcatProperties);
    }

    /**
     * This is done to disable Spring MVC dispatcherServlet
     */
    @Bean(name = "dispatcherServlet")
    public String getDispatcherServlet() {
        return "";
    }

    @Bean
    public WebApplicationExceptionResponseBuilder getWebApplicationExceptionResponseBuilder() {
        return new WebApplicationExceptionResponseBuilder();
    }

    @Bean
    public ScmContext getScmContext() {
        return new ScmContext();
    }
}
         

我关注了这些线程 https://brudenko.com/spring-bean-override, https://blog.tratif.com/2018/03/08/when-two-beans-collide/ 。但如果我在 application.properties 中设置 spring.main.allow-bean-definition-overriding=true。我开始出现以下错误:

   2020-08-30 18:24:14.438 GMT+05:30  INFO rid=NA cid=NA 13076 --- [           main] o.s.s.petclinic.PetClinicApplication     : Starting PetClinicApplication v2.3.1.BUILD-SNAPSHOT on sasas-WX-3 with PID 13076 (C:
\work\upstream\fault-tolerance-demo\target\spring-petclinic-2.3.1.BUILD-SNAPSHOT.jar started by krsoni in C:\work\upstream\fault-tolerance-demo)                                                                  
2020-08-30 18:24:14.444 GMT+05:30  INFO rid=NA cid=NA 13076 --- [           main] o.s.s.petclinic.PetClinicApplication     : No active profile set, falling back to default profiles: default                     
2020-08-30 18:24:16.293 GMT+05:30 ERROR rid=NA cid=NA 13076 --- [           main] o.s.boot.SpringApplication               : Application run failed                                                               
                                                                                                                                                                                                                  
java.lang.IllegalStateException: Error processing condition on de.codecentric.spring.boot.chaos.monkey.configuration.ChaosMonkeyConfiguration.chaosMonkeyRestEndpoint                                             
        at org.springframework.boot.autoconfigure.condition.SpringBootCondition.matches(SpringBootCondition.java:60)                                                                                              
        at org.springframework.context.annotation.ConditionEvaluator.shouldSkip(ConditionEvaluator.java:108)                                                                                                      
        at org.springframework.context.annotation.ConfigurationClassBeanDefinitionReader.loadBeanDefinitionsForBeanMethod(ConfigurationClassBeanDefinitionReader.java:184)                                        
        at org.springframework.context.annotation.ConfigurationClassBeanDefinitionReader.loadBeanDefinitionsForConfigurationClass(ConfigurationClassBeanDefinitionReader.java:144)                                
        at org.springframework.context.annotation.ConfigurationClassBeanDefinitionReader.loadBeanDefinitions(ConfigurationClassBeanDefinitionReader.java:120)                                                     
        at org.springframework.context.annotation.ConfigurationClassPostProcessor.processConfigBeanDefinitions(ConfigurationClassPostProcessor.java:331)                                                          
        at org.springframework.context.annotation.ConfigurationClassPostProcessor.postProcessBeanDefinitionRegistry(ConfigurationClassPostProcessor.java:236)                                                     
        at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanDefinitionRegistryPostProcessors(PostProcessorRegistrationDelegate.java:280)                                           
        at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:96)                                                       
        at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:707)                                                                    
        at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:533)                                                                                            
        at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:143)                                                                   
        at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:758)                                                                                                                         
        at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:750)                                                                                                                         
        at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:397)                                                                                                                  
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:315)                                                                                                                             
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:1237)                                                                                                                            
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:1226)                                                                                                                            
        at org.springframework.samples.petclinic.PetClinicApplication.main(PetClinicApplication.java:32)                                                                                                          
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)                                                                                                                                            
        at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)                                                                                                                                            
                                                                                                                                          
        at org.springframework.boot.loader.JarLauncher.main(JarLauncher.java:88)                                                                                                                                  
Caused by: java.lang.IllegalStateException: Failed to introspect Class [com.mycompany.asr.autoconfigure.asr.ASRAutoConfiguration] from ClassLoader [org.springframework.boot.loader.LaunchedURLClassLoader@5197848c]  
        at org.springframework.util.ReflectionUtils.getDeclaredMethods(ReflectionUtils.java:481)                                                                                                                  
        at org.springframework.util.ReflectionUtils.doWithMethods(ReflectionUtils.java:358)                                                                                                                       
        at org.springframework.util.ReflectionUtils.getUniqueDeclaredMethods(ReflectionUtils.java:414)                                                                                                            
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.lambda$getTypeForFactoryMethod$2(AbstractAutowireCapableBeanFactory.java:743)                                             
        at java.util.concurrent.ConcurrentHashMap.computeIfAbsent(Unknown Source)                                                                                                                                 
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.getTypeForFactoryMethod(AbstractAutowireCapableBeanFactory.java:742)                                                      
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.determineTargetType(AbstractAutowireCapableBeanFactory.java:681)                                                          
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.predictBeanType(AbstractAutowireCapableBeanFactory.java:649)                                                              
        at org.springframework.beans.factory.support.AbstractBeanFactory.isFactoryBean(AbstractBeanFactory.java:1608)                                                                                             
        at org.springframework.boot.loader.LaunchedURLClassLoader.loadClass(LaunchedURLClassLoader.java:151)                                                                                                      
        at java.lang.ClassLoader.loadClass(Unknown Source)                                                                                                                                                        
        ... 46 common frames omitted                                                                                                                                                                              
                                                                                                                                                                                                                  
2020-08-30 18:24:16.299 GMT+05:30  WARN rid=NA cid=NA 13076 --- [           main] o.s.boot.SpringApplication               : Unable to close ApplicationContext                                                   
                                                                                                                                                                                                                  
java.lang.IllegalStateException: Failed to introspect Class [com.mycompany.asr.autoconfigure.asr.ASRAutoConfiguration] from ClassLoader [org.springframework.boot.loader.LaunchedURLClassLoader@5197848c]             
        at org.springframework.util.ReflectionUtils.getDeclaredMethods(ReflectionUtils.java:481)                                                                                                                  
                                                                                                                                      
Caused by: java.lang.NoClassDefFoundError: org/springframework/boot/context/embedded/EmbeddedServletContainerCustomizer                                                                                           
        at java.lang.Class.getDeclaredMethods0(Native Method)                                                                                                                                                     
        at java.lang.Class.privateGetDeclaredMethods(Unknown Source)                                                                                                                                              
        at java.lang.Class.getDeclaredMethods(Unknown Source)                                                                                                                                                     
        at org.springframework.util.ReflectionUtils.getDeclaredMethods(ReflectionUtils.java:463)                                                                                                                  
        ... 29 common frames omitted                                                                                                                                                                              
Caused by: java.lang.ClassNotFoundException: org.springframework.boot.context.embedded.EmbeddedServletContainerCustomizer                                                                                         
        at java.net.URLClassLoader.findClass(Unknown Source)                                                                                                                                                      
        at java.lang.ClassLoader.loadClass(Unknown Source)                                                                                                                                                        
        at org.springframework.boot.loader.LaunchedURLClassLoader.loadClass(LaunchedURLClassLoader.java:151)                                                                                                      
        at java.lang.ClassLoader.loadClass(Unknown Source)                                                                                                                                                        
        ... 33 common frames omitted  

【问题讨论】:

  • spring-boot-starter-web 自动配置名称为 dispatcherServlet 的类型为 org.springframework.web.servlet.DispatcherServlet 的 bean,因此您不能将其重新定义为类型为 String 的 bean,除非您允许。 --- 如果您允许,您的 String 类型的 bean 将替换 DispatcherServlet 类型的 bean。为什么要使用该类型定义具有 非常特殊 名称的 bean?这没有道理。 Web 自动配置查找名为 dispatcherServlet 的 bean 并尝试强制找到的 bean 键入 DispatcherServlet,但您不能从 String 创建 DispatcherServlet。
  • @Andreas :字符串类型的 bean 是在一些第三方 jar 中定义的。我没有定义它。现在如何解决这个问题,因为我无法在第三方 jar 中进行更改
  • 创建名为String 的类型为String 的bean 的第三方jar 不能与spring-boot-starter-web 一起使用。它可能应该与 Spring 一起使用,而不是 Spring Boot。 --- 尝试从组件扫描中排除具有@Bean 方法的@Configuration 组件,以免弄乱您的容器。

标签: java spring spring-boot


【解决方案1】:

https://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#howto-switch-off-the-spring-mvc-dispatcherservlet

'如果你有额外的 servlet,你可以为每一个声明一个 Servlet 或 ServletRegistrationBean 类型的 @Bean,Spring Boot 会将它们透明地注册到容器中。因为 servlet 是以这种方式注册的,所以它们可以映射到 DispatcherServlet 的子上下文而不调用它。

自己配置 DispatcherServlet 并不常见,但如果您确实需要这样做,则还必须提供 DispatcherServletPath 类型的 @Bean 以提供自定义 DispatcherServlet 的路径。'

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-02-08
    • 2017-11-22
    • 2019-04-19
    • 2019-11-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-26
    相关资源
    最近更新 更多