Skip to content

Commit e048b09

Browse files
committed
ContextClosedEvent triggers early cancelling of scheduled tasks
Closes gh-24629 See gh-27090
1 parent 57ed5bf commit e048b09

File tree

1 file changed

+32
-11
lines changed

1 file changed

+32
-11
lines changed

Diff for: spring-context/src/main/java/org/springframework/scheduling/annotation/ScheduledAnnotationBeanPostProcessor.java

+32-11
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,8 @@
5151
import org.springframework.context.ApplicationContextAware;
5252
import org.springframework.context.ApplicationListener;
5353
import org.springframework.context.EmbeddedValueResolverAware;
54+
import org.springframework.context.event.ApplicationContextEvent;
55+
import org.springframework.context.event.ContextClosedEvent;
5456
import org.springframework.context.event.ContextRefreshedEvent;
5557
import org.springframework.core.MethodIntrospector;
5658
import org.springframework.core.Ordered;
@@ -108,7 +110,7 @@
108110
public class ScheduledAnnotationBeanPostProcessor
109111
implements ScheduledTaskHolder, MergedBeanDefinitionPostProcessor, DestructionAwareBeanPostProcessor,
110112
Ordered, EmbeddedValueResolverAware, BeanNameAware, BeanFactoryAware, ApplicationContextAware,
111-
SmartInitializingSingleton, ApplicationListener<ContextRefreshedEvent>, DisposableBean {
113+
SmartInitializingSingleton, DisposableBean, ApplicationListener<ApplicationContextEvent> {
112114

113115
/**
114116
* The default name of the {@link TaskScheduler} bean to pick up: {@value}.
@@ -239,16 +241,6 @@ public void afterSingletonsInstantiated() {
239241
}
240242
}
241243

242-
@Override
243-
public void onApplicationEvent(ContextRefreshedEvent event) {
244-
if (event.getApplicationContext() == this.applicationContext) {
245-
// Running in an ApplicationContext -> register tasks this late...
246-
// giving other ContextRefreshedEvent listeners a chance to perform
247-
// their work at the same time (e.g. Spring Batch's job registration).
248-
finishRegistration();
249-
}
250-
}
251-
252244
private void finishRegistration() {
253245
if (this.scheduler != null) {
254246
this.registrar.setScheduler(this.scheduler);
@@ -645,4 +637,33 @@ public void destroy() {
645637
}
646638
}
647639

640+
641+
/**
642+
* Reacts to {@link ContextRefreshedEvent} as well as {@link ContextClosedEvent}:
643+
* performing {@link #finishRegistration()} and early cancelling of scheduled tasks,
644+
* respectively.
645+
*/
646+
@Override
647+
public void onApplicationEvent(ApplicationContextEvent event) {
648+
if (event.getApplicationContext() == this.applicationContext) {
649+
if (event instanceof ContextRefreshedEvent) {
650+
// Running in an ApplicationContext -> register tasks this late...
651+
// giving other ContextRefreshedEvent listeners a chance to perform
652+
// their work at the same time (e.g. Spring Batch's job registration).
653+
finishRegistration();
654+
}
655+
else if (event instanceof ContextClosedEvent) {
656+
synchronized (this.scheduledTasks) {
657+
Collection<Set<ScheduledTask>> allTasks = this.scheduledTasks.values();
658+
for (Set<ScheduledTask> tasks : allTasks) {
659+
for (ScheduledTask task : tasks) {
660+
// At this early point, let in-progress tasks complete still
661+
task.cancel(false);
662+
}
663+
}
664+
}
665+
}
666+
}
667+
}
668+
648669
}

0 commit comments

Comments
 (0)