IdentityHashMap for scheduled tasks (avoiding hashCode calls on bean instances)
Issue: SPR-14666
This commit is contained in:
parent
a86f6d3676
commit
480cd2c2f0
|
@ -19,6 +19,7 @@ package org.springframework.scheduling.annotation;
|
|||
import java.lang.reflect.Method;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.IdentityHashMap;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
@ -111,7 +112,7 @@ public class ScheduledAnnotationBeanPostProcessor implements DestructionAwareBea
|
|||
|
||||
private final Set<Class<?>> nonAnnotatedClasses = Collections.newSetFromMap(new ConcurrentHashMap<>(64));
|
||||
|
||||
private final Map<Object, Set<ScheduledTask>> scheduledTasks = new ConcurrentHashMap<>(16);
|
||||
private final Map<Object, Set<ScheduledTask>> scheduledTasks = new IdentityHashMap<>(16);
|
||||
|
||||
|
||||
@Override
|
||||
|
@ -261,8 +262,8 @@ public class ScheduledAnnotationBeanPostProcessor implements DestructionAwareBea
|
|||
new MethodIntrospector.MetadataLookup<Set<Scheduled>>() {
|
||||
@Override
|
||||
public Set<Scheduled> inspect(Method method) {
|
||||
Set<Scheduled> scheduledMethods =
|
||||
AnnotatedElementUtils.getMergedRepeatableAnnotations(method, Scheduled.class, Schedules.class);
|
||||
Set<Scheduled> scheduledMethods = AnnotatedElementUtils.getMergedRepeatableAnnotations(
|
||||
method, Scheduled.class, Schedules.class);
|
||||
return (!scheduledMethods.isEmpty() ? scheduledMethods : null);
|
||||
}
|
||||
});
|
||||
|
@ -300,11 +301,7 @@ public class ScheduledAnnotationBeanPostProcessor implements DestructionAwareBea
|
|||
String errorMessage =
|
||||
"Exactly one of the 'cron', 'fixedDelay(String)', or 'fixedRate(String)' attributes is required";
|
||||
|
||||
Set<ScheduledTask> tasks = this.scheduledTasks.get(bean);
|
||||
if (tasks == null) {
|
||||
tasks = new LinkedHashSet<>(4);
|
||||
this.scheduledTasks.put(bean, tasks);
|
||||
}
|
||||
Set<ScheduledTask> tasks = new LinkedHashSet<>(4);
|
||||
|
||||
// Determine initial delay
|
||||
long initialDelay = scheduled.initialDelay();
|
||||
|
@ -398,6 +395,16 @@ public class ScheduledAnnotationBeanPostProcessor implements DestructionAwareBea
|
|||
|
||||
// Check whether we had any attribute set
|
||||
Assert.isTrue(processedSchedule, errorMessage);
|
||||
|
||||
// Finally register the scheduled tasks
|
||||
synchronized (this.scheduledTasks) {
|
||||
Set<ScheduledTask> registeredTasks = this.scheduledTasks.get(bean);
|
||||
if (registeredTasks == null) {
|
||||
registeredTasks = new LinkedHashSet<>(4);
|
||||
this.scheduledTasks.put(bean, registeredTasks);
|
||||
}
|
||||
registeredTasks.addAll(tasks);
|
||||
}
|
||||
}
|
||||
catch (IllegalArgumentException ex) {
|
||||
throw new IllegalStateException(
|
||||
|
@ -408,7 +415,10 @@ public class ScheduledAnnotationBeanPostProcessor implements DestructionAwareBea
|
|||
|
||||
@Override
|
||||
public void postProcessBeforeDestruction(Object bean, String beanName) {
|
||||
Set<ScheduledTask> tasks = this.scheduledTasks.remove(bean);
|
||||
Set<ScheduledTask> tasks;
|
||||
synchronized (this.scheduledTasks) {
|
||||
tasks = this.scheduledTasks.remove(bean);
|
||||
}
|
||||
if (tasks != null) {
|
||||
for (ScheduledTask task : tasks) {
|
||||
task.cancel();
|
||||
|
@ -418,18 +428,22 @@ public class ScheduledAnnotationBeanPostProcessor implements DestructionAwareBea
|
|||
|
||||
@Override
|
||||
public boolean requiresDestruction(Object bean) {
|
||||
return this.scheduledTasks.containsKey(bean);
|
||||
synchronized (this.scheduledTasks) {
|
||||
return this.scheduledTasks.containsKey(bean);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroy() {
|
||||
Collection<Set<ScheduledTask>> allTasks = this.scheduledTasks.values();
|
||||
for (Set<ScheduledTask> tasks : allTasks) {
|
||||
for (ScheduledTask task : tasks) {
|
||||
task.cancel();
|
||||
synchronized (this.scheduledTasks) {
|
||||
Collection<Set<ScheduledTask>> allTasks = this.scheduledTasks.values();
|
||||
for (Set<ScheduledTask> tasks : allTasks) {
|
||||
for (ScheduledTask task : tasks) {
|
||||
task.cancel();
|
||||
}
|
||||
}
|
||||
this.scheduledTasks.clear();
|
||||
}
|
||||
this.scheduledTasks.clear();
|
||||
this.registrar.destroy();
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue