From 6cf197864c0f967f0c3eb98e5a1a0faecdb717af Mon Sep 17 00:00:00 2001 From: Juergen Hoeller Date: Wed, 6 Jun 2018 21:25:26 +0200 Subject: [PATCH] DefaultLifecycleProcessor properly handles count for dependent beans Issue: SPR-16901 --- .../quartz/QuartzSchedulerLifecycleTests.java | 10 ++++--- .../quartz/quartzSchedulerLifecycleTests.xml | 10 +++++-- .../support/DefaultLifecycleProcessor.java | 26 +++++++------------ 3 files changed, 24 insertions(+), 22 deletions(-) diff --git a/spring-context-support/src/test/java/org/springframework/scheduling/quartz/QuartzSchedulerLifecycleTests.java b/spring-context-support/src/test/java/org/springframework/scheduling/quartz/QuartzSchedulerLifecycleTests.java index 27df9a59694..bd8156a6342 100644 --- a/spring-context-support/src/test/java/org/springframework/scheduling/quartz/QuartzSchedulerLifecycleTests.java +++ b/spring-context-support/src/test/java/org/springframework/scheduling/quartz/QuartzSchedulerLifecycleTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2017 the original author or authors. + * Copyright 2002-2018 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,7 +18,7 @@ package org.springframework.scheduling.quartz; import org.junit.Test; -import org.springframework.context.support.AbstractApplicationContext; +import org.springframework.context.ConfigurableApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import org.springframework.util.StopWatch; @@ -32,7 +32,8 @@ public class QuartzSchedulerLifecycleTests { @Test // SPR-6354 public void destroyLazyInitSchedulerWithDefaultShutdownOrderDoesNotHang() { - AbstractApplicationContext context = new ClassPathXmlApplicationContext("quartzSchedulerLifecycleTests.xml", this.getClass()); + ConfigurableApplicationContext context = + new ClassPathXmlApplicationContext("quartzSchedulerLifecycleTests.xml", getClass()); assertNotNull(context.getBean("lazyInitSchedulerWithDefaultShutdownOrder")); StopWatch sw = new StopWatch(); sw.start("lazyScheduler"); @@ -44,7 +45,8 @@ public class QuartzSchedulerLifecycleTests { @Test // SPR-6354 public void destroyLazyInitSchedulerWithCustomShutdownOrderDoesNotHang() { - AbstractApplicationContext context = new ClassPathXmlApplicationContext("quartzSchedulerLifecycleTests.xml", this.getClass()); + ConfigurableApplicationContext context = + new ClassPathXmlApplicationContext("quartzSchedulerLifecycleTests.xml", getClass()); assertNotNull(context.getBean("lazyInitSchedulerWithCustomShutdownOrder")); StopWatch sw = new StopWatch(); sw.start("lazyScheduler"); diff --git a/spring-context-support/src/test/resources/org/springframework/scheduling/quartz/quartzSchedulerLifecycleTests.xml b/spring-context-support/src/test/resources/org/springframework/scheduling/quartz/quartzSchedulerLifecycleTests.xml index 1708cce9c76..fe15a1bb1dd 100644 --- a/spring-context-support/src/test/resources/org/springframework/scheduling/quartz/quartzSchedulerLifecycleTests.xml +++ b/spring-context-support/src/test/resources/org/springframework/scheduling/quartz/quartzSchedulerLifecycleTests.xml @@ -4,9 +4,15 @@ xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> - + + + - + + + diff --git a/spring-context/src/main/java/org/springframework/context/support/DefaultLifecycleProcessor.java b/spring-context/src/main/java/org/springframework/context/support/DefaultLifecycleProcessor.java index bfb7fa8bbf9..213c1628373 100644 --- a/spring-context/src/main/java/org/springframework/context/support/DefaultLifecycleProcessor.java +++ b/spring-context/src/main/java/org/springframework/context/support/DefaultLifecycleProcessor.java @@ -252,7 +252,7 @@ public class DefaultLifecycleProcessor implements LifecycleProcessor, BeanFactor } } 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(); } } @@ -317,8 +317,6 @@ public class DefaultLifecycleProcessor implements LifecycleProcessor, BeanFactor */ private class LifecycleGroup { - private final List members = new ArrayList<>(); - private final int phase; private final long timeout; @@ -327,9 +325,13 @@ public class DefaultLifecycleProcessor implements LifecycleProcessor, BeanFactor private final boolean autoStartupOnly; - private volatile int smartMemberCount; + private final List members = new ArrayList<>(); + + private int smartMemberCount; + + public LifecycleGroup( + int phase, long timeout, Map lifecycleBeans, boolean autoStartupOnly) { - public LifecycleGroup(int phase, long timeout, Map lifecycleBeans, boolean autoStartupOnly) { this.phase = phase; this.timeout = timeout; this.lifecycleBeans = lifecycleBeans; @@ -337,10 +339,10 @@ public class DefaultLifecycleProcessor implements LifecycleProcessor, BeanFactor } public void add(String name, Lifecycle bean) { + this.members.add(new LifecycleGroupMember(name, bean)); if (bean instanceof SmartLifecycle) { this.smartMemberCount++; } - this.members.add(new LifecycleGroupMember(name, bean)); } public void start() { @@ -352,9 +354,7 @@ public class DefaultLifecycleProcessor implements LifecycleProcessor, BeanFactor } Collections.sort(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); } } @@ -369,13 +369,7 @@ public class DefaultLifecycleProcessor implements LifecycleProcessor, BeanFactor CountDownLatch latch = new CountDownLatch(this.smartMemberCount); Set countDownBeanNames = Collections.synchronizedSet(new LinkedHashSet<>()); for (LifecycleGroupMember member : this.members) { - if (this.lifecycleBeans.containsKey(member.name)) { - doStop(this.lifecycleBeans, member.name, latch, countDownBeanNames); - } - else if (member.bean instanceof SmartLifecycle) { - // already removed, must have been a dependent - latch.countDown(); - } + doStop(this.lifecycleBeans, member.name, latch, countDownBeanNames); } try { latch.await(this.timeout, TimeUnit.MILLISECONDS);