Spring 引导 - BeanDefinitionParsingException:上下文中只能存在一个 ScheduledAnnotationBeanPostProcessor
Spring Boot - BeanDefinitionParsingException: Only one ScheduledAnnotationBeanPostProcessor may exist within the context
这是对重现问题的真实场景的简化。配置过程可能看起来很奇怪,但这是因为我将所有配置 class 放在同一个项目中,但实际上它们在应用程序和一些库之间是分开的。
这是我的Spring引导应用程序主class:
@SpringBootApplication(scanBasePackageClasses={ SomeConfig.class})
public class MySpringBootApplication {
public static void main(String[] args) {
SpringApplication.run(MySpringBootApplication.class, args);
}
...
SomeConfig.java:
@Configuration
@ImportResource("classpath:library.mail-executor.xml")
public class SomeConfig{}
library.mail-executor.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:util="http://www.springframework.org/schema/util"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util.xsd ">
<bean class=xxx.MyAsyncExecutorConfig"/>
</beans>
MyAsyncExecutorConfig.java:
@Configuration
@ImportResource("classpath:library.jobs-executor.xml")
public class MyAsyncExecutorConfig {}
}
library.jobs-executor.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:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/task
http://www.springframework.org/schema/task/spring-task.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<task:annotation-driven executor="mainWorkExecutor"/>
<bean id="mainWorkExecutor" class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor">
<property name="corePoolSize" value="${jobs.corePoolSize:5}" />
<property name="maxPoolSize" value="${jobs.maxPoolSize:10}" />
<property name="queueCapacity" value="${jobs.queueCapacity:25}" />
</bean>
</beans>
总而言之,SomeConfig
导入 library.mail-executor.xml
导入 MyAsyncExecutorConfig
whis 导入 library.jobs-executor.xml
.
这是异常:配置问题:上下文中可能只存在一个ScheduledAnnotationBeanPostProcessor:
2016-09-01T13:02:56.935 ( - - - - - ) o.s.b.SpringApplication ERROR - Application startup failed
org.springframework.beans.factory.parsing.BeanDefinitionParsingException: Configuration problem: Only one ScheduledAnnotationBeanPostProcessor may exist within the context.
Offending resource: class path resource [es/mma/architecture/spring/library.jobs-executor.xml]
at org.springframework.beans.factory.parsing.FailFastProblemReporter.error(FailFastProblemReporter.java:70) ~[spring-beans-4.2.5.RELEASE.jar:4.2.5.RELEASE]
at org.springframework.beans.factory.parsing.ReaderContext.error(ReaderContext.java:85) ~[spring-beans-4.2.5.RELEASE.jar:4.2.5.RELEASE]
at org.springframework.beans.factory.parsing.ReaderContext.error(ReaderContext.java:72) ~[spring-beans-4.2.5.RELEASE.jar:4.2.5.RELEASE]
at org.springframework.scheduling.config.AnnotationDrivenBeanDefinitionParser.parse(AnnotationDrivenBeanDefinitionParser.java:90) ~[spring-context-4.2.5.RELEASE.jar:4.2.5.RELEASE]
at org.springframework.beans.factory.xml.NamespaceHandlerSupport.parse(NamespaceHandlerSupport.java:74) ~[spring-beans-4.2.5.RELEASE.jar:4.2.5.RELEASE]
at org.springframework.beans.factory.xml.BeanDefinitionParserDelegate.parseCustomElement(BeanDefinitionParserDelegate.java:1411) ~[spring-beans-4.2.5.RELEASE.jar:4.2.5.RELEASE]
at org.springframework.beans.factory.xml.BeanDefinitionParserDelegate.parseCustomElement(BeanDefinitionParserDelegate.java:1401) ~[spring-beans-4.2.5.RELEASE.jar:4.2.5.RELEASE]
at org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader.parseBeanDefinitions(DefaultBeanDefinitionDocumentReader.java:168) ~[spring-beans-4.2.5.RELEASE.jar:4.2.5.RELEASE]
at org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader.doRegisterBeanDefinitions(DefaultBeanDefinitionDocumentReader.java:138) ~[spring-beans-4.2.5.RELEASE.jar:4.2.5.RELEASE]
at org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader.registerBeanDefinitions(DefaultBeanDefinitionDocumentReader.java:94) ~[spring-beans-4.2.5.RELEASE.jar:4.2.5.RELEASE]
at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.registerBeanDefinitions(XmlBeanDefinitionReader.java:508) ~[spring-beans-4.2.5.RELEASE.jar:4.2.5.RELEASE]
at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.doLoadBeanDefinitions(XmlBeanDefinitionReader.java:392) ~[spring-beans-4.2.5.RELEASE.jar:4.2.5.RELEASE]
at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions(XmlBeanDefinitionReader.java:336) ~[spring-beans-4.2.5.RELEASE.jar:4.2.5.RELEASE]
at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions(XmlBeanDefinitionReader.java:304) ~[spring-beans-4.2.5.RELEASE.jar:4.2.5.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:181) ~[spring-beans-4.2.5.RELEASE.jar:4.2.5.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:217) ~[spring-beans-4.2.5.RELEASE.jar:4.2.5.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:188) ~[spring-beans-4.2.5.RELEASE.jar:4.2.5.RELEASE]
at org.springframework.context.annotation.ConfigurationClassBeanDefinitionReader.loadBeanDefinitionsFromImportedResources(ConfigurationClassBeanDefinitionReader.java:346) ~[spring-context-4.2.5.RELEASE.jar:4.2.5.RELEASE]
事实:
I don't have @EnableScheduling
anywhere.
Something VERY strange, if I get rid of MyAsyncExecutorConfig
and import directly library.jobs-executor.xml
on SomeConfig
, it works OK. !!!???
For instance:
SomeConfig.java:
@Configuration
@ImportResource("classpath:library.jobs-executor.xml")
public class SomeConfig{}
If I import library.jobs-executor.xml directly on
library.mail-executor.xml it also works. !!!??? For instance:
SomeConfig.java:
@Configuration
@ImportResource("classpath:library.mail-executor.xml")
public class SomeConfig{}
library.mail-executor.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:util="http://www.springframework.org/schema/util"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util.xsd ">
<import resource="classpath:library.jobs-executor.xml"/>
</beans>
所以只有在最后@Configuration
class.library.jobs-executor.xml
导入时才会出现问题。
请注意,我无法修改此流程。那个后处理器怎么好像注册了两次????
问题出在执行器上。它包括一个使用 @EnableScheduler
并创建冲突 post 处理器的指标导出器。
您可以使用 spring.metrics.export.enabled: false
禁用它或添加 @Condition
以便不导入 library.jobs-executor.xml
(如果存在):
public class InternalScheduledAnnotationProcessorDoesntExistCondition implements ConfigurationCondition{
@Override
public ConfigurationPhase getConfigurationPhase() {
return ConfigurationPhase.PARSE_CONFIGURATION;
}
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
try{
context.getRegistry().getBeanDefinition("org.springframework.context.annotation.internalScheduledAnnotationProcessor");
return false;
}catch(NoSuchBeanDefinitionException nsde){
return true;
}
}
}
MyAsyncExecutorConfig.java:
@Configuration
@Conditional(InternalScheduledAnnotationProcessorDoesntExistCondition.class)
@ImportResource("classpath:library.jobs-executor.xml")
public class MyAsyncExecutorConfig {}
这是对重现问题的真实场景的简化。配置过程可能看起来很奇怪,但这是因为我将所有配置 class 放在同一个项目中,但实际上它们在应用程序和一些库之间是分开的。
这是我的Spring引导应用程序主class:
@SpringBootApplication(scanBasePackageClasses={ SomeConfig.class})
public class MySpringBootApplication {
public static void main(String[] args) {
SpringApplication.run(MySpringBootApplication.class, args);
}
...
SomeConfig.java:
@Configuration
@ImportResource("classpath:library.mail-executor.xml")
public class SomeConfig{}
library.mail-executor.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:util="http://www.springframework.org/schema/util"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util.xsd ">
<bean class=xxx.MyAsyncExecutorConfig"/>
</beans>
MyAsyncExecutorConfig.java:
@Configuration
@ImportResource("classpath:library.jobs-executor.xml")
public class MyAsyncExecutorConfig {}
}
library.jobs-executor.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:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/task
http://www.springframework.org/schema/task/spring-task.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<task:annotation-driven executor="mainWorkExecutor"/>
<bean id="mainWorkExecutor" class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor">
<property name="corePoolSize" value="${jobs.corePoolSize:5}" />
<property name="maxPoolSize" value="${jobs.maxPoolSize:10}" />
<property name="queueCapacity" value="${jobs.queueCapacity:25}" />
</bean>
</beans>
总而言之,SomeConfig
导入 library.mail-executor.xml
导入 MyAsyncExecutorConfig
whis 导入 library.jobs-executor.xml
.
这是异常:配置问题:上下文中可能只存在一个ScheduledAnnotationBeanPostProcessor:
2016-09-01T13:02:56.935 ( - - - - - ) o.s.b.SpringApplication ERROR - Application startup failed
org.springframework.beans.factory.parsing.BeanDefinitionParsingException: Configuration problem: Only one ScheduledAnnotationBeanPostProcessor may exist within the context.
Offending resource: class path resource [es/mma/architecture/spring/library.jobs-executor.xml]
at org.springframework.beans.factory.parsing.FailFastProblemReporter.error(FailFastProblemReporter.java:70) ~[spring-beans-4.2.5.RELEASE.jar:4.2.5.RELEASE]
at org.springframework.beans.factory.parsing.ReaderContext.error(ReaderContext.java:85) ~[spring-beans-4.2.5.RELEASE.jar:4.2.5.RELEASE]
at org.springframework.beans.factory.parsing.ReaderContext.error(ReaderContext.java:72) ~[spring-beans-4.2.5.RELEASE.jar:4.2.5.RELEASE]
at org.springframework.scheduling.config.AnnotationDrivenBeanDefinitionParser.parse(AnnotationDrivenBeanDefinitionParser.java:90) ~[spring-context-4.2.5.RELEASE.jar:4.2.5.RELEASE]
at org.springframework.beans.factory.xml.NamespaceHandlerSupport.parse(NamespaceHandlerSupport.java:74) ~[spring-beans-4.2.5.RELEASE.jar:4.2.5.RELEASE]
at org.springframework.beans.factory.xml.BeanDefinitionParserDelegate.parseCustomElement(BeanDefinitionParserDelegate.java:1411) ~[spring-beans-4.2.5.RELEASE.jar:4.2.5.RELEASE]
at org.springframework.beans.factory.xml.BeanDefinitionParserDelegate.parseCustomElement(BeanDefinitionParserDelegate.java:1401) ~[spring-beans-4.2.5.RELEASE.jar:4.2.5.RELEASE]
at org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader.parseBeanDefinitions(DefaultBeanDefinitionDocumentReader.java:168) ~[spring-beans-4.2.5.RELEASE.jar:4.2.5.RELEASE]
at org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader.doRegisterBeanDefinitions(DefaultBeanDefinitionDocumentReader.java:138) ~[spring-beans-4.2.5.RELEASE.jar:4.2.5.RELEASE]
at org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader.registerBeanDefinitions(DefaultBeanDefinitionDocumentReader.java:94) ~[spring-beans-4.2.5.RELEASE.jar:4.2.5.RELEASE]
at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.registerBeanDefinitions(XmlBeanDefinitionReader.java:508) ~[spring-beans-4.2.5.RELEASE.jar:4.2.5.RELEASE]
at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.doLoadBeanDefinitions(XmlBeanDefinitionReader.java:392) ~[spring-beans-4.2.5.RELEASE.jar:4.2.5.RELEASE]
at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions(XmlBeanDefinitionReader.java:336) ~[spring-beans-4.2.5.RELEASE.jar:4.2.5.RELEASE]
at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions(XmlBeanDefinitionReader.java:304) ~[spring-beans-4.2.5.RELEASE.jar:4.2.5.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:181) ~[spring-beans-4.2.5.RELEASE.jar:4.2.5.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:217) ~[spring-beans-4.2.5.RELEASE.jar:4.2.5.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:188) ~[spring-beans-4.2.5.RELEASE.jar:4.2.5.RELEASE]
at org.springframework.context.annotation.ConfigurationClassBeanDefinitionReader.loadBeanDefinitionsFromImportedResources(ConfigurationClassBeanDefinitionReader.java:346) ~[spring-context-4.2.5.RELEASE.jar:4.2.5.RELEASE]
事实:
I don't have
@EnableScheduling
anywhere.Something VERY strange, if I get rid of
MyAsyncExecutorConfig
and import directlylibrary.jobs-executor.xml
onSomeConfig
, it works OK. !!!??? For instance:
SomeConfig.java:
@Configuration
@ImportResource("classpath:library.jobs-executor.xml")
public class SomeConfig{}
If I import library.jobs-executor.xml directly on library.mail-executor.xml it also works. !!!??? For instance:
SomeConfig.java:
@Configuration
@ImportResource("classpath:library.mail-executor.xml")
public class SomeConfig{}
library.mail-executor.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:util="http://www.springframework.org/schema/util"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util.xsd ">
<import resource="classpath:library.jobs-executor.xml"/>
</beans>
所以只有在最后@Configuration
class.library.jobs-executor.xml
导入时才会出现问题。
请注意,我无法修改此流程。那个后处理器怎么好像注册了两次????
问题出在执行器上。它包括一个使用 @EnableScheduler
并创建冲突 post 处理器的指标导出器。
您可以使用 spring.metrics.export.enabled: false
禁用它或添加 @Condition
以便不导入 library.jobs-executor.xml
(如果存在):
public class InternalScheduledAnnotationProcessorDoesntExistCondition implements ConfigurationCondition{
@Override
public ConfigurationPhase getConfigurationPhase() {
return ConfigurationPhase.PARSE_CONFIGURATION;
}
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
try{
context.getRegistry().getBeanDefinition("org.springframework.context.annotation.internalScheduledAnnotationProcessor");
return false;
}catch(NoSuchBeanDefinitionException nsde){
return true;
}
}
}
MyAsyncExecutorConfig.java:
@Configuration
@Conditional(InternalScheduledAnnotationProcessorDoesntExistCondition.class)
@ImportResource("classpath:library.jobs-executor.xml")
public class MyAsyncExecutorConfig {}