Introduce support for concurrent startup phases with timeouts

Closes gh-34634
This commit is contained in:
Juergen Hoeller
2025-04-01 22:18:26 +02:00
parent 203ca30a64
commit 48009c8534
2 changed files with 200 additions and 62 deletions

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2024 the original author or authors.
* Copyright 2002-2025 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.
@@ -16,6 +16,7 @@
package org.springframework.context.support;
import java.util.Map;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.function.Consumer;
@@ -30,6 +31,7 @@ import org.springframework.context.Lifecycle;
import org.springframework.context.LifecycleProcessor;
import org.springframework.context.SmartLifecycle;
import org.springframework.core.testfixture.EnabledForTestGroups;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
@@ -54,10 +56,11 @@ class DefaultLifecycleProcessorTests {
@Test
void customLifecycleProcessorInstance() {
StaticApplicationContext context = new StaticApplicationContext();
BeanDefinition beanDefinition = new RootBeanDefinition(DefaultLifecycleProcessor.class);
beanDefinition.getPropertyValues().addPropertyValue("timeoutPerShutdownPhase", 1000);
StaticApplicationContext context = new StaticApplicationContext();
context.registerBeanDefinition("lifecycleProcessor", beanDefinition);
context.registerBeanDefinition(StaticApplicationContext.LIFECYCLE_PROCESSOR_BEAN_NAME, beanDefinition);
context.refresh();
LifecycleProcessor bean = context.getBean("lifecycleProcessor", LifecycleProcessor.class);
Object contextLifecycleProcessor = new DirectFieldAccessor(context).getPropertyValue("lifecycleProcessor");
@@ -70,11 +73,12 @@ class DefaultLifecycleProcessorTests {
@Test
void singleSmartLifecycleAutoStartup() {
StaticApplicationContext context = new StaticApplicationContext();
CopyOnWriteArrayList<Lifecycle> startedBeans = new CopyOnWriteArrayList<>();
TestSmartLifecycleBean bean = TestSmartLifecycleBean.forStartupTests(1, startedBeans);
bean.setAutoStartup(true);
StaticApplicationContext context = new StaticApplicationContext();
context.getBeanFactory().registerSingleton("bean", bean);
assertThat(bean.isRunning()).isFalse();
context.refresh();
assertThat(bean.isRunning()).isTrue();
@@ -114,12 +118,13 @@ class DefaultLifecycleProcessorTests {
@Test
void singleSmartLifecycleAutoStartupWithFailingLifecycleBean() {
StaticApplicationContext context = new StaticApplicationContext();
CopyOnWriteArrayList<Lifecycle> startedBeans = new CopyOnWriteArrayList<>();
TestSmartLifecycleBean bean = TestSmartLifecycleBean.forStartupTests(1, startedBeans);
bean.setAutoStartup(true);
StaticApplicationContext context = new StaticApplicationContext();
context.getBeanFactory().registerSingleton("bean", bean);
context.registerSingleton("failingBean", FailingLifecycleBean.class);
assertThat(bean.isRunning()).isFalse();
assertThatExceptionOfType(ApplicationContextException.class)
.isThrownBy(context::refresh).withCauseInstanceOf(IllegalStateException.class);
@@ -130,11 +135,12 @@ class DefaultLifecycleProcessorTests {
@Test
void singleSmartLifecycleWithoutAutoStartup() {
StaticApplicationContext context = new StaticApplicationContext();
CopyOnWriteArrayList<Lifecycle> startedBeans = new CopyOnWriteArrayList<>();
TestSmartLifecycleBean bean = TestSmartLifecycleBean.forStartupTests(1, startedBeans);
bean.setAutoStartup(false);
StaticApplicationContext context = new StaticApplicationContext();
context.getBeanFactory().registerSingleton("bean", bean);
assertThat(bean.isRunning()).isFalse();
context.refresh();
assertThat(bean.isRunning()).isFalse();
@@ -148,15 +154,16 @@ class DefaultLifecycleProcessorTests {
@Test
void singleSmartLifecycleAutoStartupWithNonAutoStartupDependency() {
StaticApplicationContext context = new StaticApplicationContext();
CopyOnWriteArrayList<Lifecycle> startedBeans = new CopyOnWriteArrayList<>();
TestSmartLifecycleBean bean = TestSmartLifecycleBean.forStartupTests(1, startedBeans);
bean.setAutoStartup(true);
TestSmartLifecycleBean dependency = TestSmartLifecycleBean.forStartupTests(1, startedBeans);
dependency.setAutoStartup(false);
StaticApplicationContext context = new StaticApplicationContext();
context.getBeanFactory().registerSingleton("bean", bean);
context.getBeanFactory().registerSingleton("dependency", dependency);
context.getBeanFactory().registerDependentBean("dependency", "bean");
assertThat(bean.isRunning()).isFalse();
assertThat(dependency.isRunning()).isFalse();
context.refresh();
@@ -169,20 +176,42 @@ class DefaultLifecycleProcessorTests {
context.close();
}
@Test
void singleSmartLifecycleAutoStartupWithBootstrapExecutor() {
StaticApplicationContext context = new StaticApplicationContext();
BeanDefinition beanDefinition = new RootBeanDefinition(DefaultLifecycleProcessor.class);
beanDefinition.getPropertyValues().addPropertyValue("concurrentStartupForPhases", Map.of(1, 1000));
context.registerBeanDefinition(StaticApplicationContext.LIFECYCLE_PROCESSOR_BEAN_NAME, beanDefinition);
context.registerSingleton(StaticApplicationContext.BOOTSTRAP_EXECUTOR_BEAN_NAME, ThreadPoolTaskExecutor.class);
CopyOnWriteArrayList<Lifecycle> startedBeans = new CopyOnWriteArrayList<>();
TestSmartLifecycleBean bean = TestSmartLifecycleBean.forStartupTests(1, startedBeans);
bean.setAutoStartup(true);
context.getBeanFactory().registerSingleton("bean", bean);
assertThat(bean.isRunning()).isFalse();
context.refresh();
assertThat(bean.isRunning()).isTrue();
context.stop();
assertThat(bean.isRunning()).isFalse();
assertThat(startedBeans).hasSize(1);
context.close();
}
@Test
void smartLifecycleGroupStartup() {
StaticApplicationContext context = new StaticApplicationContext();
CopyOnWriteArrayList<Lifecycle> startedBeans = new CopyOnWriteArrayList<>();
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);
assertThat(beanMin.isRunning()).isFalse();
assertThat(bean1.isRunning()).isFalse();
assertThat(bean2.isRunning()).isFalse();
@@ -202,16 +231,17 @@ class DefaultLifecycleProcessorTests {
@Test
void contextRefreshThenStartWithMixedBeans() {
StaticApplicationContext context = new StaticApplicationContext();
CopyOnWriteArrayList<Lifecycle> startedBeans = new CopyOnWriteArrayList<>();
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);
assertThat(simpleBean1.isRunning()).isFalse();
assertThat(simpleBean2.isRunning()).isFalse();
assertThat(smartBean1.isRunning()).isFalse();
@@ -233,16 +263,17 @@ class DefaultLifecycleProcessorTests {
@Test
void contextRefreshThenStopAndRestartWithMixedBeans() {
StaticApplicationContext context = new StaticApplicationContext();
CopyOnWriteArrayList<Lifecycle> startedBeans = new CopyOnWriteArrayList<>();
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);
assertThat(simpleBean1.isRunning()).isFalse();
assertThat(simpleBean2.isRunning()).isFalse();
assertThat(smartBean1.isRunning()).isFalse();
@@ -270,16 +301,17 @@ class DefaultLifecycleProcessorTests {
@Test
void contextRefreshThenStopForRestartWithMixedBeans() {
StaticApplicationContext context = new StaticApplicationContext();
CopyOnWriteArrayList<Lifecycle> startedBeans = new CopyOnWriteArrayList<>();
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);
assertThat(simpleBean1.isRunning()).isFalse();
assertThat(simpleBean2.isRunning()).isFalse();
assertThat(smartBean1.isRunning()).isFalse();
@@ -319,6 +351,7 @@ class DefaultLifecycleProcessorTests {
@Test
@EnabledForTestGroups(LONG_RUNNING)
void smartLifecycleGroupShutdown() {
StaticApplicationContext context = new StaticApplicationContext();
CopyOnWriteArrayList<Lifecycle> stoppedBeans = new CopyOnWriteArrayList<>();
TestSmartLifecycleBean bean1 = TestSmartLifecycleBean.forShutdownTests(1, 300, stoppedBeans);
TestSmartLifecycleBean bean2 = TestSmartLifecycleBean.forShutdownTests(3, 100, stoppedBeans);
@@ -327,7 +360,6 @@ class DefaultLifecycleProcessorTests {
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);
context.getBeanFactory().registerSingleton("bean3", bean3);
@@ -335,6 +367,7 @@ class DefaultLifecycleProcessorTests {
context.getBeanFactory().registerSingleton("bean5", bean5);
context.getBeanFactory().registerSingleton("bean6", bean6);
context.getBeanFactory().registerSingleton("bean7", bean7);
context.refresh();
context.stop();
assertThat(stoppedBeans).satisfiesExactly(hasPhase(Integer.MAX_VALUE), hasPhase(3),
@@ -345,11 +378,12 @@ class DefaultLifecycleProcessorTests {
@Test
@EnabledForTestGroups(LONG_RUNNING)
void singleSmartLifecycleShutdown() {
StaticApplicationContext context = new StaticApplicationContext();
CopyOnWriteArrayList<Lifecycle> stoppedBeans = new CopyOnWriteArrayList<>();
TestSmartLifecycleBean bean = TestSmartLifecycleBean.forShutdownTests(99, 300, stoppedBeans);
StaticApplicationContext context = new StaticApplicationContext();
context.getBeanFactory().registerSingleton("bean", bean);
context.refresh();
assertThat(bean.isRunning()).isTrue();
context.stop();
assertThat(bean.isRunning()).isFalse();
@@ -359,10 +393,11 @@ class DefaultLifecycleProcessorTests {
@Test
void singleLifecycleShutdown() {
StaticApplicationContext context = new StaticApplicationContext();
CopyOnWriteArrayList<Lifecycle> stoppedBeans = new CopyOnWriteArrayList<>();
Lifecycle bean = new TestLifecycleBean(null, stoppedBeans);
StaticApplicationContext context = new StaticApplicationContext();
context.getBeanFactory().registerSingleton("bean", bean);
context.refresh();
assertThat(bean.isRunning()).isFalse();
bean.start();
@@ -375,6 +410,7 @@ class DefaultLifecycleProcessorTests {
@Test
void mixedShutdown() {
StaticApplicationContext context = new StaticApplicationContext();
CopyOnWriteArrayList<Lifecycle> stoppedBeans = new CopyOnWriteArrayList<>();
Lifecycle bean1 = TestLifecycleBean.forShutdownTests(stoppedBeans);
Lifecycle bean2 = TestSmartLifecycleBean.forShutdownTests(500, 200, stoppedBeans);
@@ -383,7 +419,6 @@ class DefaultLifecycleProcessorTests {
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);
@@ -391,6 +426,7 @@ class DefaultLifecycleProcessorTests {
context.getBeanFactory().registerSingleton("bean5", bean5);
context.getBeanFactory().registerSingleton("bean6", bean6);
context.getBeanFactory().registerSingleton("bean7", bean7);
context.refresh();
assertThat(bean2.isRunning()).isTrue();
assertThat(bean3.isRunning()).isTrue();
@@ -418,17 +454,18 @@ class DefaultLifecycleProcessorTests {
@Test
void dependencyStartedFirstEvenIfItsPhaseIsHigher() {
StaticApplicationContext context = new StaticApplicationContext();
CopyOnWriteArrayList<Lifecycle> startedBeans = new CopyOnWriteArrayList<>();
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();
assertThat(beanMin.isRunning()).isTrue();
assertThat(bean2.isRunning()).isTrue();
@@ -446,6 +483,7 @@ class DefaultLifecycleProcessorTests {
@Test
@EnabledForTestGroups(LONG_RUNNING)
void dependentShutdownFirstEvenIfItsPhaseIsLower() {
StaticApplicationContext context = new StaticApplicationContext();
CopyOnWriteArrayList<Lifecycle> stoppedBeans = new CopyOnWriteArrayList<>();
TestSmartLifecycleBean beanMin = TestSmartLifecycleBean.forShutdownTests(Integer.MIN_VALUE, 100, stoppedBeans);
TestSmartLifecycleBean bean1 = TestSmartLifecycleBean.forShutdownTests(1, 200, stoppedBeans);
@@ -453,7 +491,6 @@ class DefaultLifecycleProcessorTests {
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);
@@ -461,6 +498,7 @@ class DefaultLifecycleProcessorTests {
context.getBeanFactory().registerSingleton("bean99", bean99);
context.getBeanFactory().registerSingleton("beanMax", beanMax);
context.getBeanFactory().registerDependentBean("bean99", "bean2");
context.refresh();
assertThat(beanMin.isRunning()).isTrue();
assertThat(bean1.isRunning()).isTrue();
@@ -486,17 +524,18 @@ class DefaultLifecycleProcessorTests {
@Test
void dependencyStartedFirstAndIsSmartLifecycle() {
StaticApplicationContext context = new StaticApplicationContext();
CopyOnWriteArrayList<Lifecycle> startedBeans = new CopyOnWriteArrayList<>();
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();
@@ -514,6 +553,7 @@ class DefaultLifecycleProcessorTests {
@Test
@EnabledForTestGroups(LONG_RUNNING)
void dependentShutdownFirstAndIsSmartLifecycle() {
StaticApplicationContext context = new StaticApplicationContext();
CopyOnWriteArrayList<Lifecycle> stoppedBeans = new CopyOnWriteArrayList<>();
TestSmartLifecycleBean beanMin = TestSmartLifecycleBean.forShutdownTests(Integer.MIN_VALUE, 400, stoppedBeans);
TestSmartLifecycleBean beanNegative = TestSmartLifecycleBean.forShutdownTests(-99, 100, stoppedBeans);
@@ -521,7 +561,6 @@ class DefaultLifecycleProcessorTests {
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);
@@ -529,6 +568,7 @@ class DefaultLifecycleProcessorTests {
context.getBeanFactory().registerSingleton("bean7", bean7);
context.getBeanFactory().registerSingleton("simpleBean", simpleBean);
context.getBeanFactory().registerDependentBean("simpleBean", "beanNegative");
context.refresh();
assertThat(beanMin.isRunning()).isTrue();
assertThat(beanNegative.isRunning()).isTrue();
@@ -551,15 +591,16 @@ class DefaultLifecycleProcessorTests {
@Test
void dependencyStartedFirstButNotSmartLifecycle() {
StaticApplicationContext context = new StaticApplicationContext();
CopyOnWriteArrayList<Lifecycle> startedBeans = new CopyOnWriteArrayList<>();
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();
assertThat(beanMin.isRunning()).isTrue();
assertThat(bean7.isRunning()).isTrue();
@@ -572,19 +613,20 @@ class DefaultLifecycleProcessorTests {
@Test
@EnabledForTestGroups(LONG_RUNNING)
void dependentShutdownFirstButNotSmartLifecycle() {
StaticApplicationContext context = new StaticApplicationContext();
CopyOnWriteArrayList<Lifecycle> stoppedBeans = new CopyOnWriteArrayList<>();
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().registerDependentBean("bean2", "simpleBean");
context.refresh();
assertThat(beanMin.isRunning()).isTrue();
assertThat(bean1.isRunning()).isTrue();
@@ -611,6 +653,7 @@ class DefaultLifecycleProcessorTests {
};
}
private static class TestLifecycleBean implements Lifecycle {
private final CopyOnWriteArrayList<Lifecycle> startedBeans;