SPR-5507 The 'shutdownOrder' property of SmartLifecycle has been renamed 'phase'. The order no longer applies to shutdown only; now startup order is determined by the phase value as well. Components start in ascending order and stop in descending order.

This commit is contained in:
Mark Fisher
2009-11-24 16:07:23 +00:00
parent 1f5568fa81
commit 021663b12f
7 changed files with 541 additions and 176 deletions

View File

@@ -33,16 +33,157 @@ import org.springframework.context.SmartLifecycle;
*/
public class DefaultLifecycleProcessorTests {
@Test
public void singleSmartLifecycleAutoStartup() throws Exception {
CopyOnWriteArrayList<Lifecycle> startedBeans = new CopyOnWriteArrayList<Lifecycle>();
TestSmartLifecycleBean bean = TestSmartLifecycleBean.forStartupTests(1, startedBeans);
bean.setAutoStartup(true);
StaticApplicationContext context = new StaticApplicationContext();
context.getBeanFactory().registerSingleton("bean", bean);
assertFalse(bean.isRunning());
context.refresh();
assertTrue(bean.isRunning());
context.stop();
assertFalse(bean.isRunning());
assertEquals(1, startedBeans.size());
}
@Test
public void singleSmartLifecycleWithoutAutoStartup() throws Exception {
CopyOnWriteArrayList<Lifecycle> startedBeans = new CopyOnWriteArrayList<Lifecycle>();
TestSmartLifecycleBean bean = TestSmartLifecycleBean.forStartupTests(1, startedBeans);
bean.setAutoStartup(false);
StaticApplicationContext context = new StaticApplicationContext();
context.getBeanFactory().registerSingleton("bean", bean);
assertFalse(bean.isRunning());
context.refresh();
assertFalse(bean.isRunning());
assertEquals(0, startedBeans.size());
context.start();
assertTrue(bean.isRunning());
assertEquals(1, startedBeans.size());
context.stop();
}
@Test
public void smartLifecycleGroupStartup() throws Exception {
CopyOnWriteArrayList<Lifecycle> startedBeans = new CopyOnWriteArrayList<Lifecycle>();
TestSmartLifecycleBean beanMin = TestSmartLifecycleBean.forStartupTests(Integer.MIN_VALUE, startedBeans);
TestSmartLifecycleBean bean1 = TestSmartLifecycleBean.forStartupTests(1, startedBeans);
TestSmartLifecycleBean bean2 = TestSmartLifecycleBean.forStartupTests(2, startedBeans);
TestSmartLifecycleBean bean3 = TestSmartLifecycleBean.forStartupTests(3, startedBeans);
TestSmartLifecycleBean beanMax = TestSmartLifecycleBean.forStartupTests(Integer.MAX_VALUE, startedBeans);
StaticApplicationContext context = new StaticApplicationContext();
context.getBeanFactory().registerSingleton("bean3", bean3);
context.getBeanFactory().registerSingleton("beanMin", beanMin);
context.getBeanFactory().registerSingleton("bean2", bean2);
context.getBeanFactory().registerSingleton("beanMax", beanMax);
context.getBeanFactory().registerSingleton("bean1", bean1);
assertFalse(beanMin.isRunning());
assertFalse(bean1.isRunning());
assertFalse(bean2.isRunning());
assertFalse(bean3.isRunning());
assertFalse(beanMax.isRunning());
context.refresh();
assertTrue(beanMin.isRunning());
assertTrue(bean1.isRunning());
assertTrue(bean2.isRunning());
assertTrue(bean3.isRunning());
assertTrue(beanMax.isRunning());
context.stop();
assertEquals(5, startedBeans.size());
assertEquals(Integer.MIN_VALUE, getPhase(startedBeans.get(0)));
assertEquals(1, getPhase(startedBeans.get(1)));
assertEquals(2, getPhase(startedBeans.get(2)));
assertEquals(3, getPhase(startedBeans.get(3)));
assertEquals(Integer.MAX_VALUE, getPhase(startedBeans.get(4)));
}
@Test
public void contextRefreshThenStartWithMixedBeans() throws Exception {
CopyOnWriteArrayList<Lifecycle> startedBeans = new CopyOnWriteArrayList<Lifecycle>();
TestLifecycleBean simpleBean1 = TestLifecycleBean.forStartupTests(startedBeans);
TestLifecycleBean simpleBean2 = TestLifecycleBean.forStartupTests(startedBeans);
TestSmartLifecycleBean smartBean1 = TestSmartLifecycleBean.forStartupTests(5, startedBeans);
TestSmartLifecycleBean smartBean2 = TestSmartLifecycleBean.forStartupTests(-3, startedBeans);
StaticApplicationContext context = new StaticApplicationContext();
context.getBeanFactory().registerSingleton("simpleBean1", simpleBean1);
context.getBeanFactory().registerSingleton("smartBean1", smartBean1);
context.getBeanFactory().registerSingleton("simpleBean2", simpleBean2);
context.getBeanFactory().registerSingleton("smartBean2", smartBean2);
assertFalse(simpleBean1.isRunning());
assertFalse(simpleBean2.isRunning());
assertFalse(smartBean1.isRunning());
assertFalse(smartBean2.isRunning());
context.refresh();
assertTrue(smartBean1.isRunning());
assertTrue(smartBean2.isRunning());
assertFalse(simpleBean1.isRunning());
assertFalse(simpleBean2.isRunning());
assertEquals(2, startedBeans.size());
assertEquals(-3, getPhase(startedBeans.get(0)));
assertEquals(5, getPhase(startedBeans.get(1)));
context.start();
assertTrue(smartBean1.isRunning());
assertTrue(smartBean2.isRunning());
assertTrue(simpleBean1.isRunning());
assertTrue(simpleBean2.isRunning());
assertEquals(4, startedBeans.size());
assertEquals(0, getPhase(startedBeans.get(2)));
assertEquals(0, getPhase(startedBeans.get(3)));
}
@Test
public void contextRefreshThenStopAndRestartWithMixedBeans() throws Exception {
CopyOnWriteArrayList<Lifecycle> startedBeans = new CopyOnWriteArrayList<Lifecycle>();
TestLifecycleBean simpleBean1 = TestLifecycleBean.forStartupTests(startedBeans);
TestLifecycleBean simpleBean2 = TestLifecycleBean.forStartupTests(startedBeans);
TestSmartLifecycleBean smartBean1 = TestSmartLifecycleBean.forStartupTests(5, startedBeans);
TestSmartLifecycleBean smartBean2 = TestSmartLifecycleBean.forStartupTests(-3, startedBeans);
StaticApplicationContext context = new StaticApplicationContext();
context.getBeanFactory().registerSingleton("simpleBean1", simpleBean1);
context.getBeanFactory().registerSingleton("smartBean1", smartBean1);
context.getBeanFactory().registerSingleton("simpleBean2", simpleBean2);
context.getBeanFactory().registerSingleton("smartBean2", smartBean2);
assertFalse(simpleBean1.isRunning());
assertFalse(simpleBean2.isRunning());
assertFalse(smartBean1.isRunning());
assertFalse(smartBean2.isRunning());
context.refresh();
assertTrue(smartBean1.isRunning());
assertTrue(smartBean2.isRunning());
assertFalse(simpleBean1.isRunning());
assertFalse(simpleBean2.isRunning());
assertEquals(2, startedBeans.size());
assertEquals(-3, getPhase(startedBeans.get(0)));
assertEquals(5, getPhase(startedBeans.get(1)));
context.stop();
assertFalse(simpleBean1.isRunning());
assertFalse(simpleBean2.isRunning());
assertFalse(smartBean1.isRunning());
assertFalse(smartBean2.isRunning());
context.start();
assertTrue(smartBean1.isRunning());
assertTrue(smartBean2.isRunning());
assertTrue(simpleBean1.isRunning());
assertTrue(simpleBean2.isRunning());
assertEquals(6, startedBeans.size());
assertEquals(-3, getPhase(startedBeans.get(2)));
assertEquals(0, getPhase(startedBeans.get(3)));
assertEquals(0, getPhase(startedBeans.get(4)));
assertEquals(5, getPhase(startedBeans.get(5)));
}
@Test
public void smartLifecycleGroupShutdown() throws Exception {
CopyOnWriteArrayList<Lifecycle> stoppedBeans = new CopyOnWriteArrayList<Lifecycle>();
TestSmartLifecycleBean bean1 = new TestSmartLifecycleBean(1, 300, stoppedBeans);
TestSmartLifecycleBean bean2 = new TestSmartLifecycleBean(3, 100, stoppedBeans);
TestSmartLifecycleBean bean3 = new TestSmartLifecycleBean(1, 600, stoppedBeans);
TestSmartLifecycleBean bean4 = new TestSmartLifecycleBean(2, 400, stoppedBeans);
TestSmartLifecycleBean bean5 = new TestSmartLifecycleBean(2, 700, stoppedBeans);
TestSmartLifecycleBean bean6 = new TestSmartLifecycleBean(Integer.MAX_VALUE, 200, stoppedBeans);
TestSmartLifecycleBean bean7 = new TestSmartLifecycleBean(3, 200, stoppedBeans);
TestSmartLifecycleBean bean1 = TestSmartLifecycleBean.forShutdownTests(1, 300, stoppedBeans);
TestSmartLifecycleBean bean2 = TestSmartLifecycleBean.forShutdownTests(3, 100, stoppedBeans);
TestSmartLifecycleBean bean3 = TestSmartLifecycleBean.forShutdownTests(1, 600, stoppedBeans);
TestSmartLifecycleBean bean4 = TestSmartLifecycleBean.forShutdownTests(2, 400, stoppedBeans);
TestSmartLifecycleBean bean5 = TestSmartLifecycleBean.forShutdownTests(2, 700, stoppedBeans);
TestSmartLifecycleBean bean6 = TestSmartLifecycleBean.forShutdownTests(Integer.MAX_VALUE, 200, stoppedBeans);
TestSmartLifecycleBean bean7 = TestSmartLifecycleBean.forShutdownTests(3, 200, stoppedBeans);
StaticApplicationContext context = new StaticApplicationContext();
context.getBeanFactory().registerSingleton("bean1", bean1);
context.getBeanFactory().registerSingleton("bean2", bean2);
@@ -53,19 +194,19 @@ public class DefaultLifecycleProcessorTests {
context.getBeanFactory().registerSingleton("bean7", bean7);
context.refresh();
context.stop();
assertEquals(1, getShutdownOrder(stoppedBeans.get(0)));
assertEquals(1, getShutdownOrder(stoppedBeans.get(1)));
assertEquals(2, getShutdownOrder(stoppedBeans.get(2)));
assertEquals(2, getShutdownOrder(stoppedBeans.get(3)));
assertEquals(3, getShutdownOrder(stoppedBeans.get(4)));
assertEquals(3, getShutdownOrder(stoppedBeans.get(5)));
assertEquals(Integer.MAX_VALUE, getShutdownOrder(stoppedBeans.get(6)));
assertEquals(Integer.MAX_VALUE, getPhase(stoppedBeans.get(0)));
assertEquals(3, getPhase(stoppedBeans.get(1)));
assertEquals(3, getPhase(stoppedBeans.get(2)));
assertEquals(2, getPhase(stoppedBeans.get(3)));
assertEquals(2, getPhase(stoppedBeans.get(4)));
assertEquals(1, getPhase(stoppedBeans.get(5)));
assertEquals(1, getPhase(stoppedBeans.get(6)));
}
@Test
public void singleSmartLifecycleShutdown() throws Exception {
CopyOnWriteArrayList<Lifecycle> stoppedBeans = new CopyOnWriteArrayList<Lifecycle>();
TestSmartLifecycleBean bean = new TestSmartLifecycleBean(99, 300, stoppedBeans);
TestSmartLifecycleBean bean = TestSmartLifecycleBean.forShutdownTests(99, 300, stoppedBeans);
StaticApplicationContext context = new StaticApplicationContext();
context.getBeanFactory().registerSingleton("bean", bean);
context.refresh();
@@ -79,7 +220,7 @@ public class DefaultLifecycleProcessorTests {
@Test
public void singleLifecycleShutdown() throws Exception {
CopyOnWriteArrayList<Lifecycle> stoppedBeans = new CopyOnWriteArrayList<Lifecycle>();
Lifecycle bean = new TestLifecycleBean(stoppedBeans);
Lifecycle bean = new TestLifecycleBean(null, stoppedBeans);
StaticApplicationContext context = new StaticApplicationContext();
context.getBeanFactory().registerSingleton("bean", bean);
context.refresh();
@@ -95,120 +236,277 @@ public class DefaultLifecycleProcessorTests {
@Test
public void mixedShutdown() throws Exception {
CopyOnWriteArrayList<Lifecycle> stoppedBeans = new CopyOnWriteArrayList<Lifecycle>();
Lifecycle bean1 = new TestLifecycleBean(stoppedBeans);
Lifecycle bean2 = new TestSmartLifecycleBean(500, 200, stoppedBeans);
Lifecycle bean3 = new TestSmartLifecycleBean(Integer.MAX_VALUE, 100, stoppedBeans);
Lifecycle bean4 = new TestLifecycleBean(stoppedBeans);
Lifecycle bean5 = new TestSmartLifecycleBean(1, 200, stoppedBeans);
Lifecycle bean1 = TestLifecycleBean.forShutdownTests(stoppedBeans);
Lifecycle bean2 = TestSmartLifecycleBean.forShutdownTests(500, 200, stoppedBeans);
Lifecycle bean3 = TestSmartLifecycleBean.forShutdownTests(Integer.MAX_VALUE, 100, stoppedBeans);
Lifecycle bean4 = TestLifecycleBean.forShutdownTests(stoppedBeans);
Lifecycle bean5 = TestSmartLifecycleBean.forShutdownTests(1, 200, stoppedBeans);
Lifecycle bean6 = TestSmartLifecycleBean.forShutdownTests(-1, 100, stoppedBeans);
Lifecycle bean7 = TestSmartLifecycleBean.forShutdownTests(Integer.MIN_VALUE, 300, stoppedBeans);
StaticApplicationContext context = new StaticApplicationContext();
context.getBeanFactory().registerSingleton("bean1", bean1);
context.getBeanFactory().registerSingleton("bean2", bean2);
context.getBeanFactory().registerSingleton("bean3", bean3);
context.getBeanFactory().registerSingleton("bean4", bean4);
context.getBeanFactory().registerSingleton("bean5", bean5);
context.getBeanFactory().registerSingleton("bean6", bean6);
context.getBeanFactory().registerSingleton("bean7", bean7);
context.refresh();
assertTrue(bean2.isRunning());
assertTrue(bean3.isRunning());
assertTrue(bean5.isRunning());
assertTrue(bean6.isRunning());
assertTrue(bean7.isRunning());
assertFalse(bean1.isRunning());
assertFalse(bean4.isRunning());
bean1.start();
bean4.start();
assertTrue(bean1.isRunning());
assertTrue(bean2.isRunning());
assertTrue(bean3.isRunning());
assertTrue(bean4.isRunning());
assertTrue(bean5.isRunning());
context.stop();
assertFalse(bean1.isRunning());
assertFalse(bean2.isRunning());
assertFalse(bean3.isRunning());
assertFalse(bean4.isRunning());
assertFalse(bean5.isRunning());
assertEquals(5, stoppedBeans.size());
assertEquals(1, getShutdownOrder(stoppedBeans.get(0)));
assertEquals(500, getShutdownOrder(stoppedBeans.get(1)));
assertEquals(Integer.MAX_VALUE, getShutdownOrder(stoppedBeans.get(2)));
assertEquals(Integer.MAX_VALUE, getShutdownOrder(stoppedBeans.get(3)));
assertEquals(Integer.MAX_VALUE, getShutdownOrder(stoppedBeans.get(4)));
assertFalse(bean6.isRunning());
assertFalse(bean7.isRunning());
assertEquals(7, stoppedBeans.size());
assertEquals(Integer.MAX_VALUE, getPhase(stoppedBeans.get(0)));
assertEquals(500, getPhase(stoppedBeans.get(1)));
assertEquals(1, getPhase(stoppedBeans.get(2)));
assertEquals(0, getPhase(stoppedBeans.get(3)));
assertEquals(0, getPhase(stoppedBeans.get(4)));
assertEquals(-1, getPhase(stoppedBeans.get(5)));
assertEquals(Integer.MIN_VALUE, getPhase(stoppedBeans.get(6)));
}
@Test
public void dependantShutdownFirstEvenIfItsOrderIsHigher() throws Exception {
CopyOnWriteArrayList<Lifecycle> stoppedBeans = new CopyOnWriteArrayList<Lifecycle>();
TestSmartLifecycleBean bean1 = new TestSmartLifecycleBean(1, 200, stoppedBeans);
TestSmartLifecycleBean bean99 = new TestSmartLifecycleBean(99, 100, stoppedBeans);
TestSmartLifecycleBean bean2 = new TestSmartLifecycleBean(2, 300, stoppedBeans);
TestSmartLifecycleBean bean7 = new TestSmartLifecycleBean(7, 400, stoppedBeans);
TestSmartLifecycleBean beanLast = new TestSmartLifecycleBean(Integer.MAX_VALUE, 400, stoppedBeans);
public void dependencyStartedFirstEvenIfItsPhaseIsHigher() throws Exception {
CopyOnWriteArrayList<Lifecycle> startedBeans = new CopyOnWriteArrayList<Lifecycle>();
TestSmartLifecycleBean beanMin = TestSmartLifecycleBean.forStartupTests(Integer.MIN_VALUE, startedBeans);
TestSmartLifecycleBean bean2 = TestSmartLifecycleBean.forStartupTests(2, startedBeans);
TestSmartLifecycleBean bean99 = TestSmartLifecycleBean.forStartupTests(99, startedBeans);
TestSmartLifecycleBean beanMax = TestSmartLifecycleBean.forStartupTests(Integer.MAX_VALUE, startedBeans);
StaticApplicationContext context = new StaticApplicationContext();
context.getBeanFactory().registerSingleton("beanMin", beanMin);
context.getBeanFactory().registerSingleton("bean2", bean2);
context.getBeanFactory().registerSingleton("bean99", bean99);
context.getBeanFactory().registerSingleton("beanMax", beanMax);
context.getBeanFactory().registerDependentBean("bean99", "bean2");
context.refresh();
assertTrue(beanMin.isRunning());
assertTrue(bean2.isRunning());
assertTrue(bean99.isRunning());
assertTrue(beanMax.isRunning());
assertEquals(4, startedBeans.size());
assertEquals(Integer.MIN_VALUE, getPhase(startedBeans.get(0)));
assertEquals(99, getPhase(startedBeans.get(1)));
assertEquals(bean99, startedBeans.get(1));
assertEquals(2, getPhase(startedBeans.get(2)));
assertEquals(bean2, startedBeans.get(2));
assertEquals(Integer.MAX_VALUE, getPhase(startedBeans.get(3)));
context.stop();
}
@Test
public void dependentShutdownFirstEvenIfItsPhaseIsLower() throws Exception {
CopyOnWriteArrayList<Lifecycle> stoppedBeans = new CopyOnWriteArrayList<Lifecycle>();
TestSmartLifecycleBean beanMin = TestSmartLifecycleBean.forShutdownTests(Integer.MIN_VALUE, 100, stoppedBeans);
TestSmartLifecycleBean bean1 = TestSmartLifecycleBean.forShutdownTests(1, 200, stoppedBeans);
TestSmartLifecycleBean bean99 = TestSmartLifecycleBean.forShutdownTests(99, 100, stoppedBeans);
TestSmartLifecycleBean bean2 = TestSmartLifecycleBean.forShutdownTests(2, 300, stoppedBeans);
TestSmartLifecycleBean bean7 = TestSmartLifecycleBean.forShutdownTests(7, 400, stoppedBeans);
TestSmartLifecycleBean beanMax = TestSmartLifecycleBean.forShutdownTests(Integer.MAX_VALUE, 400, stoppedBeans);
StaticApplicationContext context = new StaticApplicationContext();
context.getBeanFactory().registerSingleton("beanMin", beanMin);
context.getBeanFactory().registerSingleton("bean1", bean1);
context.getBeanFactory().registerSingleton("bean2", bean2);
context.getBeanFactory().registerSingleton("bean7", bean7);
context.getBeanFactory().registerSingleton("bean99", bean99);
context.getBeanFactory().registerSingleton("beanLast", beanLast);
context.getBeanFactory().registerDependentBean("bean2", "bean99");
context.getBeanFactory().registerSingleton("beanMax", beanMax);
context.getBeanFactory().registerDependentBean("bean99", "bean2");
context.refresh();
assertTrue(beanMin.isRunning());
assertTrue(bean1.isRunning());
assertTrue(bean2.isRunning());
assertTrue(bean7.isRunning());
assertTrue(bean99.isRunning());
assertTrue(beanMax.isRunning());
context.stop();
assertFalse(beanMin.isRunning());
assertFalse(bean1.isRunning());
assertFalse(bean2.isRunning());
assertFalse(bean7.isRunning());
assertFalse(bean99.isRunning());
assertEquals(5, stoppedBeans.size());
assertEquals(1, getShutdownOrder(stoppedBeans.get(0)));
assertEquals(99, getShutdownOrder(stoppedBeans.get(1)));
assertEquals(2, getShutdownOrder(stoppedBeans.get(2)));
assertEquals(7, getShutdownOrder(stoppedBeans.get(3)));
assertEquals(Integer.MAX_VALUE, getShutdownOrder(stoppedBeans.get(4)));
assertFalse(beanMax.isRunning());
assertEquals(6, stoppedBeans.size());
assertEquals(Integer.MAX_VALUE, getPhase(stoppedBeans.get(0)));
assertEquals(2, getPhase(stoppedBeans.get(1)));
assertEquals(bean2, stoppedBeans.get(1));
assertEquals(99, getPhase(stoppedBeans.get(2)));
assertEquals(bean99, stoppedBeans.get(2));
assertEquals(7, getPhase(stoppedBeans.get(3)));
assertEquals(1, getPhase(stoppedBeans.get(4)));
assertEquals(Integer.MIN_VALUE, getPhase(stoppedBeans.get(5)));
}
@Test
public void dependantShutdownFirstEvenIfNotSmartLifecycle() throws Exception {
CopyOnWriteArrayList<Lifecycle> stoppedBeans = new CopyOnWriteArrayList<Lifecycle>();
TestSmartLifecycleBean bean1 = new TestSmartLifecycleBean(1, 200, stoppedBeans);
TestLifecycleBean simpleBean = new TestLifecycleBean(stoppedBeans);
TestSmartLifecycleBean bean2 = new TestSmartLifecycleBean(2, 300, stoppedBeans);
TestSmartLifecycleBean bean7 = new TestSmartLifecycleBean(7, 400, stoppedBeans);
TestSmartLifecycleBean beanLast = new TestSmartLifecycleBean(Integer.MAX_VALUE, 400, stoppedBeans);
public void dependencyStartedFirstAndIsSmartLifecycle() throws Exception {
CopyOnWriteArrayList<Lifecycle> startedBeans = new CopyOnWriteArrayList<Lifecycle>();
TestSmartLifecycleBean beanNegative = TestSmartLifecycleBean.forStartupTests(-99, startedBeans);
TestSmartLifecycleBean bean99 = TestSmartLifecycleBean.forStartupTests(99, startedBeans);
TestSmartLifecycleBean bean7 = TestSmartLifecycleBean.forStartupTests(7, startedBeans);
TestLifecycleBean simpleBean = TestLifecycleBean.forStartupTests(startedBeans);
StaticApplicationContext context = new StaticApplicationContext();
context.getBeanFactory().registerSingleton("beanNegative", beanNegative);
context.getBeanFactory().registerSingleton("bean7", bean7);
context.getBeanFactory().registerSingleton("bean99", bean99);
context.getBeanFactory().registerSingleton("simpleBean", simpleBean);
context.getBeanFactory().registerDependentBean("bean7", "simpleBean");
context.refresh();
context.stop();
startedBeans.clear();
// clean start so that simpleBean is included
context.start();
assertTrue(beanNegative.isRunning());
assertTrue(bean99.isRunning());
assertTrue(bean7.isRunning());
assertTrue(simpleBean.isRunning());
assertEquals(4, startedBeans.size());
assertEquals(-99, getPhase(startedBeans.get(0)));
assertEquals(7, getPhase(startedBeans.get(1)));
assertEquals(0, getPhase(startedBeans.get(2)));
assertEquals(99, getPhase(startedBeans.get(3)));
context.stop();
}
@Test
public void dependentShutdownFirstAndIsSmartLifecycle() throws Exception {
CopyOnWriteArrayList<Lifecycle> stoppedBeans = new CopyOnWriteArrayList<Lifecycle>();
TestSmartLifecycleBean beanMin = TestSmartLifecycleBean.forShutdownTests(Integer.MIN_VALUE, 400, stoppedBeans);
TestSmartLifecycleBean beanNegative = TestSmartLifecycleBean.forShutdownTests(-99, 100, stoppedBeans);
TestSmartLifecycleBean bean1 = TestSmartLifecycleBean.forShutdownTests(1, 200, stoppedBeans);
TestSmartLifecycleBean bean2 = TestSmartLifecycleBean.forShutdownTests(2, 300, stoppedBeans);
TestSmartLifecycleBean bean7 = TestSmartLifecycleBean.forShutdownTests(7, 400, stoppedBeans);
TestLifecycleBean simpleBean = TestLifecycleBean.forShutdownTests(stoppedBeans);
StaticApplicationContext context = new StaticApplicationContext();
context.getBeanFactory().registerSingleton("beanMin", beanMin);
context.getBeanFactory().registerSingleton("beanNegative", beanNegative);
context.getBeanFactory().registerSingleton("bean1", bean1);
context.getBeanFactory().registerSingleton("bean2", bean2);
context.getBeanFactory().registerSingleton("bean7", bean7);
context.getBeanFactory().registerSingleton("simpleBean", simpleBean);
context.getBeanFactory().registerDependentBean("simpleBean", "beanNegative");
context.refresh();
assertTrue(beanMin.isRunning());
assertTrue(beanNegative.isRunning());
assertTrue(bean1.isRunning());
assertTrue(bean2.isRunning());
assertTrue(bean7.isRunning());
// should start since it's a dependency of an auto-started bean
assertTrue(simpleBean.isRunning());
context.stop();
assertFalse(beanMin.isRunning());
assertFalse(beanNegative.isRunning());
assertFalse(bean1.isRunning());
assertFalse(bean2.isRunning());
assertFalse(bean7.isRunning());
assertFalse(simpleBean.isRunning());
assertEquals(6, stoppedBeans.size());
assertEquals(7, getPhase(stoppedBeans.get(0)));
assertEquals(2, getPhase(stoppedBeans.get(1)));
assertEquals(1, getPhase(stoppedBeans.get(2)));
assertEquals(-99, getPhase(stoppedBeans.get(3)));
assertEquals(0, getPhase(stoppedBeans.get(4)));
assertEquals(Integer.MIN_VALUE, getPhase(stoppedBeans.get(5)));
}
@Test
public void dependencyStartedFirstButNotSmartLifecycle() throws Exception {
CopyOnWriteArrayList<Lifecycle> startedBeans = new CopyOnWriteArrayList<Lifecycle>();
TestSmartLifecycleBean beanMin = TestSmartLifecycleBean.forStartupTests(Integer.MIN_VALUE, startedBeans);
TestSmartLifecycleBean bean7 = TestSmartLifecycleBean.forStartupTests(7, startedBeans);
TestLifecycleBean simpleBean = TestLifecycleBean.forStartupTests(startedBeans);
StaticApplicationContext context = new StaticApplicationContext();
context.getBeanFactory().registerSingleton("beanMin", beanMin);
context.getBeanFactory().registerSingleton("bean7", bean7);
context.getBeanFactory().registerSingleton("simpleBean", simpleBean);
context.getBeanFactory().registerDependentBean("simpleBean", "beanMin");
context.refresh();
assertTrue(beanMin.isRunning());
assertTrue(bean7.isRunning());
assertTrue(simpleBean.isRunning());
assertEquals(3, startedBeans.size());
assertEquals(0, getPhase(startedBeans.get(0)));
assertEquals(Integer.MIN_VALUE, getPhase(startedBeans.get(1)));
assertEquals(7, getPhase(startedBeans.get(2)));
context.stop();
}
@Test
public void dependentShutdownFirstButNotSmartLifecycle() throws Exception {
CopyOnWriteArrayList<Lifecycle> stoppedBeans = new CopyOnWriteArrayList<Lifecycle>();
TestSmartLifecycleBean bean1 = TestSmartLifecycleBean.forShutdownTests(1, 200, stoppedBeans);
TestLifecycleBean simpleBean = TestLifecycleBean.forShutdownTests(stoppedBeans);
TestSmartLifecycleBean bean2 = TestSmartLifecycleBean.forShutdownTests(2, 300, stoppedBeans);
TestSmartLifecycleBean bean7 = TestSmartLifecycleBean.forShutdownTests(7, 400, stoppedBeans);
TestSmartLifecycleBean beanMin = TestSmartLifecycleBean.forShutdownTests(Integer.MIN_VALUE, 400, stoppedBeans);
StaticApplicationContext context = new StaticApplicationContext();
context.getBeanFactory().registerSingleton("beanMin", beanMin);
context.getBeanFactory().registerSingleton("bean1", bean1);
context.getBeanFactory().registerSingleton("bean2", bean2);
context.getBeanFactory().registerSingleton("bean7", bean7);
context.getBeanFactory().registerSingleton("simpleBean", simpleBean);
context.getBeanFactory().registerSingleton("beanLast", beanLast);
context.getBeanFactory().registerDependentBean("bean2", "simpleBean");
context.refresh();
assertTrue(beanMin.isRunning());
assertTrue(bean1.isRunning());
assertTrue(bean2.isRunning());
assertTrue(bean7.isRunning());
assertFalse(simpleBean.isRunning());
simpleBean.start();
assertTrue(simpleBean.isRunning());
context.stop();
assertFalse(beanMin.isRunning());
assertFalse(bean1.isRunning());
assertFalse(bean2.isRunning());
assertFalse(bean7.isRunning());
assertFalse(simpleBean.isRunning());
assertEquals(5, stoppedBeans.size());
assertEquals(1, getShutdownOrder(stoppedBeans.get(0)));
assertEquals(Integer.MAX_VALUE, getShutdownOrder(stoppedBeans.get(1)));
assertEquals(2, getShutdownOrder(stoppedBeans.get(2)));
assertEquals(7, getShutdownOrder(stoppedBeans.get(3)));
assertEquals(Integer.MAX_VALUE, getShutdownOrder(stoppedBeans.get(4)));
assertEquals(7, getPhase(stoppedBeans.get(0)));
assertEquals(0, getPhase(stoppedBeans.get(1)));
assertEquals(2, getPhase(stoppedBeans.get(2)));
assertEquals(1, getPhase(stoppedBeans.get(3)));
assertEquals(Integer.MIN_VALUE, getPhase(stoppedBeans.get(4)));
}
private static int getShutdownOrder(Lifecycle lifecycle) {
private static int getPhase(Lifecycle lifecycle) {
return (lifecycle instanceof SmartLifecycle) ?
((SmartLifecycle) lifecycle).getShutdownOrder() : Integer.MAX_VALUE;
((SmartLifecycle) lifecycle).getPhase() : 0;
}
private class TestLifecycleBean implements Lifecycle {
private static class TestLifecycleBean implements Lifecycle {
protected final CopyOnWriteArrayList<Lifecycle> stoppedBeans;
private final CopyOnWriteArrayList<Lifecycle> startedBeans;
private final CopyOnWriteArrayList<Lifecycle> stoppedBeans;
private volatile boolean running;
TestLifecycleBean(CopyOnWriteArrayList<Lifecycle> stoppedBeans) {
static TestLifecycleBean forStartupTests(CopyOnWriteArrayList<Lifecycle> startedBeans) {
return new TestLifecycleBean(startedBeans, null);
}
static TestLifecycleBean forShutdownTests(CopyOnWriteArrayList<Lifecycle> stoppedBeans) {
return new TestLifecycleBean(null, stoppedBeans);
}
private TestLifecycleBean(CopyOnWriteArrayList<Lifecycle> startedBeans, CopyOnWriteArrayList<Lifecycle> stoppedBeans) {
this.startedBeans = startedBeans;
this.stoppedBeans = stoppedBeans;
}
@@ -217,45 +515,65 @@ public class DefaultLifecycleProcessorTests {
}
public void start() {
if (this.startedBeans != null) {
this.startedBeans.add(this);
}
this.running = true;
}
public void stop() {
this.stoppedBeans.add(this);
if (this.stoppedBeans != null) {
this.stoppedBeans.add(this);
}
this.running = false;
}
}
private class TestSmartLifecycleBean extends TestLifecycleBean implements SmartLifecycle {
private static class TestSmartLifecycleBean extends TestLifecycleBean implements SmartLifecycle {
private final int shutdownOrder;
private final int phase;
private final int shutdownDelay;
private volatile boolean autoStartup = true;
TestSmartLifecycleBean(int shutdownOrder, int shutdownDelay, CopyOnWriteArrayList<Lifecycle> stoppedBeans) {
super(stoppedBeans);
this.shutdownOrder = shutdownOrder;
static TestSmartLifecycleBean forStartupTests(int phase, CopyOnWriteArrayList<Lifecycle> startedBeans) {
return new TestSmartLifecycleBean(phase, 0, startedBeans, null);
}
static TestSmartLifecycleBean forShutdownTests(int phase, int shutdownDelay, CopyOnWriteArrayList<Lifecycle> stoppedBeans) {
return new TestSmartLifecycleBean(phase, shutdownDelay, null, stoppedBeans);
}
private TestSmartLifecycleBean(int phase, int shutdownDelay, CopyOnWriteArrayList<Lifecycle> startedBeans, CopyOnWriteArrayList<Lifecycle> stoppedBeans) {
super(startedBeans, stoppedBeans);
this.phase = phase;
this.shutdownDelay = shutdownDelay;
}
public int getShutdownOrder() {
return this.shutdownOrder;
public int getPhase() {
return this.phase;
}
public boolean isAutoStartup() {
return true;
return this.autoStartup;
}
public void setAutoStartup(boolean autoStartup) {
this.autoStartup = autoStartup;
}
public void stop(final Runnable callback) {
// calling stop() before the delay to preserve
// invocation order in the 'stoppedBeans' list
stop();
final int delay = this.shutdownDelay;
new Thread(new Runnable() {
public void run() {
try {
Thread.sleep(delay);
stop();
}
catch (InterruptedException e) {
// ignore