Skip to content

Commit a897e3f

Browse files
committed
refined DefaultLifecycleProcessor's start/stop logging and stop exception handling (SPR-6769, SPR-6770)
1 parent 59b8a13 commit a897e3f

File tree

1 file changed

+69
-32
lines changed

1 file changed

+69
-32
lines changed

org.springframework.context/src/main/java/org/springframework/context/support/DefaultLifecycleProcessor.java

Lines changed: 69 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2009 the original author or authors.
2+
* Copyright 2002-2010 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -20,8 +20,10 @@
2020
import java.util.Collections;
2121
import java.util.HashMap;
2222
import java.util.LinkedHashMap;
23+
import java.util.LinkedHashSet;
2324
import java.util.List;
2425
import java.util.Map;
26+
import java.util.Set;
2527
import java.util.concurrent.CountDownLatch;
2628
import java.util.concurrent.TimeUnit;
2729

@@ -47,7 +49,7 @@
4749
*/
4850
public class DefaultLifecycleProcessor implements LifecycleProcessor, BeanFactoryAware {
4951

50-
private final Log logger = LogFactory.getLog(this.getClass());
52+
private final Log logger = LogFactory.getLog(getClass());
5153

5254
private volatile long timeoutPerShutdownPhase = 30000;
5355

@@ -156,7 +158,13 @@ private void doStart(Map<String, ? extends Lifecycle> lifecycleBeans, String bea
156158
doStart(lifecycleBeans, dependency);
157159
}
158160
if (!bean.isRunning()) {
161+
if (logger.isDebugEnabled()) {
162+
logger.debug("Starting bean '" + beanName + "' of type [" + bean.getClass() + "]");
163+
}
159164
bean.start();
165+
if (logger.isDebugEnabled()) {
166+
logger.debug("Successfully started bean '" + beanName + "'");
167+
}
160168
}
161169
lifecycleBeans.remove(beanName);
162170
}
@@ -190,28 +198,51 @@ private void stopBeans() {
190198
* @param lifecycleBeans Map with bean name as key and Lifecycle instance as value
191199
* @param beanName the name of the bean to stop
192200
*/
193-
private void doStop(Map<String, ? extends Lifecycle> lifecycleBeans, String beanName, final CountDownLatch latch) {
201+
private void doStop(Map<String, ? extends Lifecycle> lifecycleBeans, final String beanName,
202+
final CountDownLatch latch, final Set<String> countDownBeanNames) {
203+
194204
Lifecycle bean = lifecycleBeans.get(beanName);
195205
if (bean != null) {
196206
String[] dependentBeans = this.beanFactory.getDependentBeans(beanName);
197207
for (String dependentBean : dependentBeans) {
198-
doStop(lifecycleBeans, dependentBean, latch);
208+
doStop(lifecycleBeans, dependentBean, latch, countDownBeanNames);
199209
}
200-
if (bean.isRunning()) {
201-
if (bean instanceof SmartLifecycle) {
202-
((SmartLifecycle) bean).stop(new Runnable() {
203-
public void run() {
204-
latch.countDown();
210+
try {
211+
if (bean.isRunning()) {
212+
if (bean instanceof SmartLifecycle) {
213+
if (logger.isDebugEnabled()) {
214+
logger.debug("Asking bean '" + beanName + "' of type [" + bean.getClass() + "] to stop");
215+
}
216+
countDownBeanNames.add(beanName);
217+
((SmartLifecycle) bean).stop(new Runnable() {
218+
public void run() {
219+
latch.countDown();
220+
countDownBeanNames.remove(beanName);
221+
if (logger.isDebugEnabled()) {
222+
logger.debug("Bean '" + beanName + "' completed its stop procedure");
223+
}
224+
}
225+
});
226+
}
227+
else {
228+
if (logger.isDebugEnabled()) {
229+
logger.debug("Stopping bean '" + beanName + "' of type [" + bean.getClass() + "]");
230+
}
231+
bean.stop();
232+
if (logger.isDebugEnabled()) {
233+
logger.debug("Successfully stopped bean '" + beanName + "'");
205234
}
206-
});
235+
}
207236
}
208-
else {
209-
bean.stop();
237+
else if (bean instanceof SmartLifecycle) {
238+
// don't wait for beans that aren't running
239+
latch.countDown();
210240
}
211241
}
212-
else if (bean instanceof SmartLifecycle) {
213-
// don't wait for beans that aren't running
214-
latch.countDown();
242+
catch (Throwable ex) {
243+
if (logger.isWarnEnabled()) {
244+
logger.warn("Failed to stop bean '" + beanName + "'", ex);
245+
}
215246
}
216247
lifecycleBeans.remove(beanName);
217248
}
@@ -288,26 +319,33 @@ public void add(String name, Lifecycle bean) {
288319
}
289320

290321
public void start() {
291-
if (members.size() == 0) {
322+
if (this.members.isEmpty()) {
292323
return;
293324
}
294-
Collections.sort(members);
295-
for (LifecycleGroupMember member : members) {
296-
if (lifecycleBeans.containsKey(member.name)) {
297-
doStart(lifecycleBeans, member.name);
325+
if (logger.isInfoEnabled()) {
326+
logger.info("Starting beans in phase " + this.phase);
327+
}
328+
Collections.sort(this.members);
329+
for (LifecycleGroupMember member : this.members) {
330+
if (this.lifecycleBeans.containsKey(member.name)) {
331+
doStart(this.lifecycleBeans, member.name);
298332
}
299333
}
300334
}
301335

302336
public void stop() {
303-
if (members.size() == 0) {
337+
if (this.members.isEmpty()) {
304338
return;
305339
}
306-
Collections.sort(members, Collections.reverseOrder());
307-
final CountDownLatch latch = new CountDownLatch(this.smartMemberCount);
308-
for (LifecycleGroupMember member : members) {
309-
if (lifecycleBeans.containsKey(member.name)) {
310-
doStop(lifecycleBeans, member.name, latch);
340+
if (logger.isInfoEnabled()) {
341+
logger.info("Stopping beans in phase " + this.phase);
342+
}
343+
Collections.sort(this.members, Collections.reverseOrder());
344+
CountDownLatch latch = new CountDownLatch(this.smartMemberCount);
345+
Set<String> countDownBeanNames = Collections.synchronizedSet(new LinkedHashSet<String>());
346+
for (LifecycleGroupMember member : this.members) {
347+
if (this.lifecycleBeans.containsKey(member.name)) {
348+
doStop(this.lifecycleBeans, member.name, latch, countDownBeanNames);
311349
}
312350
else if (member.bean instanceof SmartLifecycle) {
313351
// already removed, must have been a dependent
@@ -316,14 +354,13 @@ else if (member.bean instanceof SmartLifecycle) {
316354
}
317355
try {
318356
latch.await(this.timeout, TimeUnit.MILLISECONDS);
319-
if (latch.getCount() != 0) {
320-
if (logger.isWarnEnabled()) {
321-
logger.warn("failed to shutdown beans with phase value " +
322-
this.phase + " within timeout of " + this.timeout);
323-
}
357+
if (latch.getCount() > 0 && !countDownBeanNames.isEmpty() && logger.isWarnEnabled()) {
358+
logger.warn("Failed to shut down " + countDownBeanNames.size() + " bean" +
359+
(countDownBeanNames.size() > 1 ? "s" : "") + " with phase value " +
360+
this.phase + " within timeout of " + this.timeout + ": " + countDownBeanNames);
324361
}
325362
}
326-
catch (InterruptedException e) {
363+
catch (InterruptedException ex) {
327364
Thread.currentThread().interrupt();
328365
}
329366
}

0 commit comments

Comments
 (0)