Browse Source

DefaultLifecycleProcessor properly counts dependent beans in same phase

Issue: SPR-16901
pull/1946/head
Juergen Hoeller 8 years ago
parent
commit
6f41d4ec4d
  1. 36
      spring-context/src/main/java/org/springframework/context/support/DefaultLifecycleProcessor.java

36
spring-context/src/main/java/org/springframework/context/support/DefaultLifecycleProcessor.java

@ -19,6 +19,7 @@ package org.springframework.context.support;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import java.util.LinkedHashSet; import java.util.LinkedHashSet;
import java.util.List; import java.util.List;
@ -162,7 +163,7 @@ public class DefaultLifecycleProcessor implements LifecycleProcessor, BeanFactor
/** /**
* Start the specified bean as part of the given set of Lifecycle beans, * Start the specified bean as part of the given set of Lifecycle beans,
* making sure that any beans that it depends on are started first. * making sure that any beans that it depends on are started first.
* @param lifecycleBeans Map with bean name as key and Lifecycle instance as value * @param lifecycleBeans a Map with bean name as key and Lifecycle instance as value
* @param beanName the name of the bean to start * @param beanName the name of the bean to start
*/ */
private void doStart(Map<String, ? extends Lifecycle> lifecycleBeans, String beanName, boolean autoStartupOnly) { private void doStart(Map<String, ? extends Lifecycle> lifecycleBeans, String beanName, boolean autoStartupOnly) {
@ -175,7 +176,7 @@ public class DefaultLifecycleProcessor implements LifecycleProcessor, BeanFactor
if (!bean.isRunning() && if (!bean.isRunning() &&
(!autoStartupOnly || !(bean instanceof SmartLifecycle) || ((SmartLifecycle) bean).isAutoStartup())) { (!autoStartupOnly || !(bean instanceof SmartLifecycle) || ((SmartLifecycle) bean).isAutoStartup())) {
if (logger.isDebugEnabled()) { if (logger.isDebugEnabled()) {
logger.debug("Starting bean '" + beanName + "' of type [" + bean.getClass() + "]"); logger.debug("Starting bean '" + beanName + "' of type [" + bean.getClass().getName() + "]");
} }
try { try {
bean.start(); bean.start();
@ -214,7 +215,7 @@ public class DefaultLifecycleProcessor implements LifecycleProcessor, BeanFactor
/** /**
* Stop the specified bean as part of the given set of Lifecycle beans, * Stop the specified bean as part of the given set of Lifecycle beans,
* making sure that any beans that depends on it are stopped first. * making sure that any beans that depends on it are stopped first.
* @param lifecycleBeans Map with bean name as key and Lifecycle instance as value * @param lifecycleBeans a Map with bean name as key and Lifecycle instance as value
* @param beanName the name of the bean to stop * @param beanName the name of the bean to stop
*/ */
private void doStop(Map<String, ? extends Lifecycle> lifecycleBeans, final String beanName, private void doStop(Map<String, ? extends Lifecycle> lifecycleBeans, final String beanName,
@ -230,7 +231,8 @@ public class DefaultLifecycleProcessor implements LifecycleProcessor, BeanFactor
if (bean.isRunning()) { if (bean.isRunning()) {
if (bean instanceof SmartLifecycle) { if (bean instanceof SmartLifecycle) {
if (logger.isDebugEnabled()) { if (logger.isDebugEnabled()) {
logger.debug("Asking bean '" + beanName + "' of type [" + bean.getClass() + "] to stop"); logger.debug("Asking bean '" + beanName + "' of type [" +
bean.getClass().getName() + "] to stop");
} }
countDownBeanNames.add(beanName); countDownBeanNames.add(beanName);
((SmartLifecycle) bean).stop(() -> { ((SmartLifecycle) bean).stop(() -> {
@ -243,7 +245,8 @@ public class DefaultLifecycleProcessor implements LifecycleProcessor, BeanFactor
} }
else { else {
if (logger.isDebugEnabled()) { if (logger.isDebugEnabled()) {
logger.debug("Stopping bean '" + beanName + "' of type [" + bean.getClass() + "]"); logger.debug("Stopping bean '" + beanName + "' of type [" +
bean.getClass().getName() + "]");
} }
bean.stop(); bean.stop();
if (logger.isDebugEnabled()) { if (logger.isDebugEnabled()) {
@ -252,7 +255,7 @@ public class DefaultLifecycleProcessor implements LifecycleProcessor, BeanFactor
} }
} }
else if (bean instanceof SmartLifecycle) { else if (bean instanceof SmartLifecycle) {
// don't wait for beans that aren't running // Don't wait for beans that aren't running...
latch.countDown(); latch.countDown();
} }
} }
@ -317,8 +320,6 @@ public class DefaultLifecycleProcessor implements LifecycleProcessor, BeanFactor
*/ */
private class LifecycleGroup { private class LifecycleGroup {
private final List<LifecycleGroupMember> members = new ArrayList<>();
private final int phase; private final int phase;
private final long timeout; private final long timeout;
@ -327,9 +328,13 @@ public class DefaultLifecycleProcessor implements LifecycleProcessor, BeanFactor
private final boolean autoStartupOnly; private final boolean autoStartupOnly;
private volatile int smartMemberCount; private final List<LifecycleGroupMember> members = new ArrayList<>();
private int smartMemberCount;
public LifecycleGroup(
int phase, long timeout, Map<String, ? extends Lifecycle> lifecycleBeans, boolean autoStartupOnly) {
public LifecycleGroup(int phase, long timeout, Map<String, ? extends Lifecycle> lifecycleBeans, boolean autoStartupOnly) {
this.phase = phase; this.phase = phase;
this.timeout = timeout; this.timeout = timeout;
this.lifecycleBeans = lifecycleBeans; this.lifecycleBeans = lifecycleBeans;
@ -337,10 +342,10 @@ public class DefaultLifecycleProcessor implements LifecycleProcessor, BeanFactor
} }
public void add(String name, Lifecycle bean) { public void add(String name, Lifecycle bean) {
this.members.add(new LifecycleGroupMember(name, bean));
if (bean instanceof SmartLifecycle) { if (bean instanceof SmartLifecycle) {
this.smartMemberCount++; this.smartMemberCount++;
} }
this.members.add(new LifecycleGroupMember(name, bean));
} }
public void start() { public void start() {
@ -352,9 +357,7 @@ public class DefaultLifecycleProcessor implements LifecycleProcessor, BeanFactor
} }
Collections.sort(this.members); Collections.sort(this.members);
for (LifecycleGroupMember member : this.members) { for (LifecycleGroupMember member : this.members) {
if (this.lifecycleBeans.containsKey(member.name)) { doStart(this.lifecycleBeans, member.name, this.autoStartupOnly);
doStart(this.lifecycleBeans, member.name, this.autoStartupOnly);
}
} }
} }
@ -368,12 +371,13 @@ public class DefaultLifecycleProcessor implements LifecycleProcessor, BeanFactor
this.members.sort(Collections.reverseOrder()); this.members.sort(Collections.reverseOrder());
CountDownLatch latch = new CountDownLatch(this.smartMemberCount); CountDownLatch latch = new CountDownLatch(this.smartMemberCount);
Set<String> countDownBeanNames = Collections.synchronizedSet(new LinkedHashSet<>()); Set<String> countDownBeanNames = Collections.synchronizedSet(new LinkedHashSet<>());
Set<String> lifecycleBeanNames = new HashSet<>(this.lifecycleBeans.keySet());
for (LifecycleGroupMember member : this.members) { for (LifecycleGroupMember member : this.members) {
if (this.lifecycleBeans.containsKey(member.name)) { if (lifecycleBeanNames.contains(member.name)) {
doStop(this.lifecycleBeans, member.name, latch, countDownBeanNames); doStop(this.lifecycleBeans, member.name, latch, countDownBeanNames);
} }
else if (member.bean instanceof SmartLifecycle) { else if (member.bean instanceof SmartLifecycle) {
// already removed, must have been a dependent // Already removed: must have been a dependent bean from another phase
latch.countDown(); latch.countDown();
} }
} }

Loading…
Cancel
Save