gpt4 book ai didi

java - 为什么 Spring 4 只允许在一个上下文中使用一个 TaskScheduler?

转载 作者:IT老高 更新时间:2023-10-28 13:57:00 26 4
gpt4 key购买 nike

我们有一个 Spring Web 应用程序,我们要从 Spring 3.2 移植到 Spring 4。当 Web 应用程序启动时,我们的应用程序有几个子上下文组合成一个运行时上下文。

我们在两个子上下文中使用单独的 TaskScheduler。使用 Spring 3.2 可以正常工作;使用 Spring 4 时,我们会收到以下消息的异常:

java.lang.IllegalStateException: More than one TaskScheduler and/or ScheduledExecutorService  exist within the context. Remove all but one of the beans; or implement the SchedulingConfigurer interface and call ScheduledTaskRegistrar#setScheduler explicitly within the configureTasks() callback. Found the following beans: [commonScheduler, communicationTaskScheduler]
at org.springframework.scheduling.annotation.ScheduledAnnotationBeanPostProcessor.onApplicationEvent(ScheduledAnnotationBeanPostProcessor.java:289) ~[spring-context-4.0.1.RELEASE.jar:4.0.1.RELEASE]
at org.springframework.scheduling.annotation.ScheduledAnnotationBeanPostProcessor.onApplicationEvent(ScheduledAnnotationBeanPostProcessor.java:72) ~[spring-context-4.0.1.RELEASE.jar:4.0.1.RELEASE]
at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:98) ~[spring-context-4.0.1.RELEASE.jar:4.0.1.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:333) ~[spring-context-4.0.1.RELEASE.jar:4.0.1.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.finishRefresh(AbstractApplicationContext.java:776) ~[spring-context-4.0.1.RELEASE.jar:4.0.1.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:485) ~[spring-context-4.0.1.RELEASE.jar:4.0.1.RELEASE]
at org.springframework.web.context.ContextLoader.configureAndRefreshWebApplicationContext(ContextLoader.java:403) ~[spring-web-4.0.1.RELEASE.jar:4.0.1.RELEASE]
at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:306) ~[spring-web-4.0.1.RELEASE.jar:4.0.1.RELEASE]
at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:106) ~[spring-web-4.0.1.RELEASE.jar:4.0.1.RELEASE]
at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4961) ~[catalina.jar:7.0.50]
at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5455) ~[catalina.jar:7.0.50]
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150) ~[catalina.jar:7.0.50]
at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:901) ~[catalina.jar:7.0.50]
at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:877) ~[catalina.jar:7.0.50]
at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:634) ~[catalina.jar:7.0.50]
at org.apache.catalina.startup.HostConfig.deployWAR(HostConfig.java:1074) ~[catalina.jar:7.0.26]
at org.apache.catalina.startup.HostConfig$DeployWar.run(HostConfig.java:1858) ~[catalina.jar:7.0.26]
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471) ~[na:1.7.0_25]
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:334) ~[na:1.7.0_25]
at java.util.concurrent.FutureTask.run(FutureTask.java:166) ~[na:1.7.0_25]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145) ~[na:1.7.0_25]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615) ~[na:1.7.0_25]
at java.lang.Thread.run(Thread.java:724) ~[na:1.7.0_25]

一个调度器通过以下方式定义:

<?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:task="http://www.springframework.org/schema/task"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-4.0.xsd">

<!-- Enables annotation-driven task scheduling; detects @Scheduled- and
@Async-annotated process methods to be invoked via proxy -->
<task:annotation-driven mode="aspectj" />
<task:scheduler id="commonScheduler" pool-size="5" />

</beans>

另一个调度器定义在(为了清楚起见删除了额外的bean):

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

<context:spring-configured />

<bean id="communicationExecutor"
class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor">
<property name="corePoolSize" value="15" />
<property name="maxPoolSize" value="20" />
<property name="queueCapacity" value="20" />
</bean>
<bean id="communicationTaskScheduler"
class="org.springframework.scheduling.concurrent.ConcurrentTaskScheduler">
<property name="concurrentExecutor" ref="communicationExecutor" />
</bean>

</beans>

上下文在运行时使用(为清楚起见删除了其他上下文):

<beans xmlns="http://www.springframework.org/schema/beans"  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd">

<import resource="classpath:spring/tasks-context.xml" />
<import resource="classpath:spring/collectors-context.xml" />
</beans>

为什么 Spring 4 有这个限制?应该如何解决?

最佳答案

是的,这肯定是行为上的改变。看来 ScheduledAnnotationBeanPostProcessor现在每个上下文限制为 2 个调度程序。我使用 Spring 4 的新 WebSocket 消息代理遇到了这个问题,因为它为 Simple STOMP 代理和 SockJS 适配器分配了 2 个调度程序。当我添加自己的内容时,它与您收到的相同信息完全不同。我发现我不得不通过错误而不是文档来找出这个限制,这很烦人。 Spring 4 文档中似乎没有描述这个问题。

解决方案是创建自己的 SchedulingConfigurer 来管理自己的 TaskScheduler。我怀疑原因是只有一个并且需要添加额外的 TaskScheduler 实现才能将它们彼此隔离。我做了这样的事情:

@Configuration
@EnableScheduling
public class MySchedulingConfigurer implements SchedulingConfigurer
{
@Bean
public TimedThingy timedThingy()
{
return new TimedThingy();
}

@Bean()
public ThreadPoolTaskScheduler taskScheduler() {
return new ThreadPoolTaskScheduler();
}

@Override
public void configureTasks(ScheduledTaskRegistrar taskRegistrar)
{
taskRegistrar.setTaskScheduler(taskScheduler());
taskRegistrar.addFixedRateTask(new Runnable()
{
public void run()
{
timedThingy().sendIt();
}
}, 1000);
}
}

一旦我这样做了,问题就消失了,事情就按预期工作了。不利的一面是您不能使用像 @Scheduled 等注释。但是您确实获得了更多控制权并且一切正常。希望这会有所帮助。

关于java - 为什么 Spring 4 只允许在一个上下文中使用一个 TaskScheduler?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21758116/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com