mirror of
https://github.com/spring-projects/spring-framework.git
synced 2026-05-03 04:19:47 +01:00
Introduce support for concurrent startup phases with timeouts
Closes gh-34634
This commit is contained in:
+136
-41
@@ -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");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -26,9 +26,12 @@ import java.util.List;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.TreeMap;
|
import java.util.TreeMap;
|
||||||
|
import java.util.concurrent.CompletableFuture;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.concurrent.CountDownLatch;
|
import java.util.concurrent.CountDownLatch;
|
||||||
import java.util.concurrent.CyclicBarrier;
|
import java.util.concurrent.CyclicBarrier;
|
||||||
|
import java.util.concurrent.ExecutionException;
|
||||||
|
import java.util.concurrent.Executor;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
import org.apache.commons.logging.Log;
|
import org.apache.commons.logging.Log;
|
||||||
@@ -52,6 +55,7 @@ import org.springframework.core.SpringProperties;
|
|||||||
import org.springframework.lang.Nullable;
|
import org.springframework.lang.Nullable;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
import org.springframework.util.ClassUtils;
|
import org.springframework.util.ClassUtils;
|
||||||
|
import org.springframework.util.CollectionUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Spring's default implementation of the {@link LifecycleProcessor} strategy.
|
* Spring's default implementation of the {@link LifecycleProcessor} strategy.
|
||||||
@@ -61,12 +65,23 @@ import org.springframework.util.ClassUtils;
|
|||||||
* interactions on a {@link org.springframework.context.ConfigurableApplicationContext}.
|
* interactions on a {@link org.springframework.context.ConfigurableApplicationContext}.
|
||||||
*
|
*
|
||||||
* <p>As of 6.1, this also includes support for JVM checkpoint/restore (Project CRaC)
|
* <p>As of 6.1, this also includes support for JVM checkpoint/restore (Project CRaC)
|
||||||
* when the {@code org.crac:crac} dependency on the classpath.
|
* when the {@code org.crac:crac} dependency is on the classpath. All running beans
|
||||||
|
* will get stopped and restarted according to the CRaC checkpoint/restore callbacks.
|
||||||
|
*
|
||||||
|
* <p>As of 6.2, this processor can be configured with custom timeouts for specific
|
||||||
|
* shutdown phases, applied to {@link SmartLifecycle#stop(Runnable)} implementations.
|
||||||
|
* As of 6.2.6, there is also support for the concurrent startup of specific phases
|
||||||
|
* with individual timeouts, triggering the {@link SmartLifecycle#start()} callbacks
|
||||||
|
* of all associated beans asynchronously and then waiting for all of them to return,
|
||||||
|
* as an alternative to the default sequential startup of beans without a timeout.
|
||||||
*
|
*
|
||||||
* @author Mark Fisher
|
* @author Mark Fisher
|
||||||
* @author Juergen Hoeller
|
* @author Juergen Hoeller
|
||||||
* @author Sebastien Deleuze
|
* @author Sebastien Deleuze
|
||||||
* @since 3.0
|
* @since 3.0
|
||||||
|
* @see SmartLifecycle#getPhase()
|
||||||
|
* @see #setConcurrentStartupForPhase
|
||||||
|
* @see #setTimeoutForShutdownPhase
|
||||||
*/
|
*/
|
||||||
public class DefaultLifecycleProcessor implements LifecycleProcessor, BeanFactoryAware {
|
public class DefaultLifecycleProcessor implements LifecycleProcessor, BeanFactoryAware {
|
||||||
|
|
||||||
@@ -102,6 +117,8 @@ public class DefaultLifecycleProcessor implements LifecycleProcessor, BeanFactor
|
|||||||
|
|
||||||
private final Log logger = LogFactory.getLog(getClass());
|
private final Log logger = LogFactory.getLog(getClass());
|
||||||
|
|
||||||
|
private final Map<Integer, Long> concurrentStartupForPhases = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
private final Map<Integer, Long> timeoutsForShutdownPhases = new ConcurrentHashMap<>();
|
private final Map<Integer, Long> timeoutsForShutdownPhases = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
private volatile long timeoutPerShutdownPhase = 10000;
|
private volatile long timeoutPerShutdownPhase = 10000;
|
||||||
@@ -130,20 +147,59 @@ public class DefaultLifecycleProcessor implements LifecycleProcessor, BeanFactor
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Switch to concurrent startup for each given phase (group of {@link SmartLifecycle}
|
||||||
|
* beans with the same 'phase' value) with corresponding timeouts.
|
||||||
|
* <p><b>Note: By default, the startup for every phase will be sequential without
|
||||||
|
* a timeout. Calling this setter with timeouts for the given phases switches to a
|
||||||
|
* mode where the beans in these phases will be started concurrently, cancelling
|
||||||
|
* the startup if the corresponding timeout is not met for any of these phases.</b>
|
||||||
|
* <p>For an actual concurrent startup, a bootstrap {@code Executor} needs to be
|
||||||
|
* set for the application context, typically through a "bootstrapExecutor" bean.
|
||||||
|
* @param phasesWithTimeouts a map of phase values (matching
|
||||||
|
* {@link SmartLifecycle#getPhase()}) and corresponding timeout values
|
||||||
|
* (in milliseconds)
|
||||||
|
* @since 6.2.6
|
||||||
|
* @see SmartLifecycle#getPhase()
|
||||||
|
* @see org.springframework.beans.factory.config.ConfigurableBeanFactory#getBootstrapExecutor()
|
||||||
|
*/
|
||||||
|
public void setConcurrentStartupForPhases(Map<Integer, Long> phasesWithTimeouts) {
|
||||||
|
this.concurrentStartupForPhases.putAll(phasesWithTimeouts);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Switch to concurrent startup for a specific phase (group of {@link SmartLifecycle}
|
||||||
|
* beans with the same 'phase' value) with a corresponding timeout.
|
||||||
|
* <p><b>Note: By default, the startup for every phase will be sequential without
|
||||||
|
* a timeout. Calling this setter with a timeout for the given phase switches to a
|
||||||
|
* mode where the beans in this phase will be started concurrently, cancelling
|
||||||
|
* the startup if the corresponding timeout is not met for this phase.</b>
|
||||||
|
* <p>For an actual concurrent startup, a bootstrap {@code Executor} needs to be
|
||||||
|
* set for the application context, typically through a "bootstrapExecutor" bean.
|
||||||
|
* @param phase the phase value (matching {@link SmartLifecycle#getPhase()})
|
||||||
|
* @param timeout the corresponding timeout value (in milliseconds)
|
||||||
|
* @since 6.2.6
|
||||||
|
* @see SmartLifecycle#getPhase()
|
||||||
|
* @see org.springframework.beans.factory.config.ConfigurableBeanFactory#getBootstrapExecutor()
|
||||||
|
*/
|
||||||
|
public void setConcurrentStartupForPhase(int phase, long timeout) {
|
||||||
|
this.concurrentStartupForPhases.put(phase, timeout);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Specify the maximum time allotted for the shutdown of each given phase
|
* Specify the maximum time allotted for the shutdown of each given phase
|
||||||
* (group of {@link SmartLifecycle} beans with the same 'phase' value).
|
* (group of {@link SmartLifecycle} beans with the same 'phase' value).
|
||||||
* <p>In case of no specific timeout configured, the default timeout per
|
* <p>In case of no specific timeout configured, the default timeout per
|
||||||
* shutdown phase will apply: 10000 milliseconds (10 seconds) as of 6.2.
|
* shutdown phase will apply: 10000 milliseconds (10 seconds) as of 6.2.
|
||||||
* @param timeoutsForShutdownPhases a map of phase values (matching
|
* @param phasesWithTimeouts a map of phase values (matching
|
||||||
* {@link SmartLifecycle#getPhase()}) and corresponding timeout values
|
* {@link SmartLifecycle#getPhase()}) and corresponding timeout values
|
||||||
* (in milliseconds)
|
* (in milliseconds)
|
||||||
* @since 6.2
|
* @since 6.2
|
||||||
* @see SmartLifecycle#getPhase()
|
* @see SmartLifecycle#getPhase()
|
||||||
* @see #setTimeoutPerShutdownPhase
|
* @see #setTimeoutPerShutdownPhase
|
||||||
*/
|
*/
|
||||||
public void setTimeoutsForShutdownPhases(Map<Integer, Long> timeoutsForShutdownPhases) {
|
public void setTimeoutsForShutdownPhases(Map<Integer, Long> phasesWithTimeouts) {
|
||||||
this.timeoutsForShutdownPhases.putAll(timeoutsForShutdownPhases);
|
this.timeoutsForShutdownPhases.putAll(phasesWithTimeouts);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -171,17 +227,15 @@ public class DefaultLifecycleProcessor implements LifecycleProcessor, BeanFactor
|
|||||||
this.timeoutPerShutdownPhase = timeoutPerShutdownPhase;
|
this.timeoutPerShutdownPhase = timeoutPerShutdownPhase;
|
||||||
}
|
}
|
||||||
|
|
||||||
private long determineTimeout(int phase) {
|
|
||||||
Long timeout = this.timeoutsForShutdownPhases.get(phase);
|
|
||||||
return (timeout != null ? timeout : this.timeoutPerShutdownPhase);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setBeanFactory(BeanFactory beanFactory) {
|
public void setBeanFactory(BeanFactory beanFactory) {
|
||||||
if (!(beanFactory instanceof ConfigurableListableBeanFactory clbf)) {
|
if (!(beanFactory instanceof ConfigurableListableBeanFactory clbf)) {
|
||||||
throw new IllegalArgumentException(
|
throw new IllegalArgumentException(
|
||||||
"DefaultLifecycleProcessor requires a ConfigurableListableBeanFactory: " + beanFactory);
|
"DefaultLifecycleProcessor requires a ConfigurableListableBeanFactory: " + beanFactory);
|
||||||
}
|
}
|
||||||
|
if (!this.concurrentStartupForPhases.isEmpty() && clbf.getBootstrapExecutor() == null) {
|
||||||
|
throw new IllegalStateException("'bootstrapExecutor' needs to be configured for concurrent startup");
|
||||||
|
}
|
||||||
this.beanFactory = clbf;
|
this.beanFactory = clbf;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -191,6 +245,22 @@ public class DefaultLifecycleProcessor implements LifecycleProcessor, BeanFactor
|
|||||||
return beanFactory;
|
return beanFactory;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Executor getBootstrapExecutor() {
|
||||||
|
Executor executor = getBeanFactory().getBootstrapExecutor();
|
||||||
|
Assert.state(executor != null, "No 'bootstrapExecutor' available");
|
||||||
|
return executor;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
private Long determineConcurrentStartup(int phase) {
|
||||||
|
return this.concurrentStartupForPhases.get(phase);
|
||||||
|
}
|
||||||
|
|
||||||
|
private long determineShutdownTimeout(int phase) {
|
||||||
|
Long timeout = this.timeoutsForShutdownPhases.get(phase);
|
||||||
|
return (timeout != null ? timeout : this.timeoutPerShutdownPhase);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Lifecycle implementation
|
// Lifecycle implementation
|
||||||
|
|
||||||
@@ -285,9 +355,8 @@ public class DefaultLifecycleProcessor implements LifecycleProcessor, BeanFactor
|
|||||||
lifecycleBeans.forEach((beanName, bean) -> {
|
lifecycleBeans.forEach((beanName, bean) -> {
|
||||||
if (!autoStartupOnly || isAutoStartupCandidate(beanName, bean)) {
|
if (!autoStartupOnly || isAutoStartupCandidate(beanName, bean)) {
|
||||||
int startupPhase = getPhase(bean);
|
int startupPhase = getPhase(bean);
|
||||||
phases.computeIfAbsent(startupPhase,
|
phases.computeIfAbsent(startupPhase, phase -> new LifecycleGroup(phase, lifecycleBeans, autoStartupOnly))
|
||||||
phase -> new LifecycleGroup(phase, determineTimeout(phase), lifecycleBeans, autoStartupOnly)
|
.add(beanName, bean);
|
||||||
).add(beanName, bean);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -308,30 +377,41 @@ public class DefaultLifecycleProcessor implements LifecycleProcessor, BeanFactor
|
|||||||
* @param lifecycleBeans a 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, @Nullable List<CompletableFuture<?>> futures) {
|
||||||
|
|
||||||
Lifecycle bean = lifecycleBeans.remove(beanName);
|
Lifecycle bean = lifecycleBeans.remove(beanName);
|
||||||
if (bean != null && bean != this) {
|
if (bean != null && bean != this) {
|
||||||
String[] dependenciesForBean = getBeanFactory().getDependenciesForBean(beanName);
|
String[] dependenciesForBean = getBeanFactory().getDependenciesForBean(beanName);
|
||||||
for (String dependency : dependenciesForBean) {
|
for (String dependency : dependenciesForBean) {
|
||||||
doStart(lifecycleBeans, dependency, autoStartupOnly);
|
doStart(lifecycleBeans, dependency, autoStartupOnly, futures);
|
||||||
}
|
}
|
||||||
if (!bean.isRunning() && (!autoStartupOnly || toBeStarted(beanName, bean))) {
|
if (!bean.isRunning() && (!autoStartupOnly || toBeStarted(beanName, bean))) {
|
||||||
if (logger.isTraceEnabled()) {
|
if (futures != null) {
|
||||||
logger.trace("Starting bean '" + beanName + "' of type [" + bean.getClass().getName() + "]");
|
futures.add(CompletableFuture.runAsync(() -> doStart(beanName, bean), getBootstrapExecutor()));
|
||||||
}
|
}
|
||||||
try {
|
else {
|
||||||
bean.start();
|
doStart(beanName, bean);
|
||||||
}
|
|
||||||
catch (Throwable ex) {
|
|
||||||
throw new ApplicationContextException("Failed to start bean '" + beanName + "'", ex);
|
|
||||||
}
|
|
||||||
if (logger.isDebugEnabled()) {
|
|
||||||
logger.debug("Successfully started bean '" + beanName + "'");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void doStart(String beanName, Lifecycle bean) {
|
||||||
|
if (logger.isTraceEnabled()) {
|
||||||
|
logger.trace("Starting bean '" + beanName + "' of type [" + bean.getClass().getName() + "]");
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
bean.start();
|
||||||
|
}
|
||||||
|
catch (Throwable ex) {
|
||||||
|
throw new ApplicationContextException("Failed to start bean '" + beanName + "'", ex);
|
||||||
|
}
|
||||||
|
if (logger.isDebugEnabled()) {
|
||||||
|
logger.debug("Successfully started bean '" + beanName + "'");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private boolean toBeStarted(String beanName, Lifecycle bean) {
|
private boolean toBeStarted(String beanName, Lifecycle bean) {
|
||||||
Set<String> stoppedBeans = this.stoppedBeans;
|
Set<String> stoppedBeans = this.stoppedBeans;
|
||||||
return (stoppedBeans != null ? stoppedBeans.contains(beanName) :
|
return (stoppedBeans != null ? stoppedBeans.contains(beanName) :
|
||||||
@@ -344,9 +424,8 @@ public class DefaultLifecycleProcessor implements LifecycleProcessor, BeanFactor
|
|||||||
|
|
||||||
lifecycleBeans.forEach((beanName, bean) -> {
|
lifecycleBeans.forEach((beanName, bean) -> {
|
||||||
int shutdownPhase = getPhase(bean);
|
int shutdownPhase = getPhase(bean);
|
||||||
phases.computeIfAbsent(shutdownPhase,
|
phases.computeIfAbsent(shutdownPhase, phase -> new LifecycleGroup(phase, lifecycleBeans, false))
|
||||||
phase -> new LifecycleGroup(phase, determineTimeout(phase), lifecycleBeans, false)
|
.add(beanName, bean);
|
||||||
).add(beanName, bean);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!phases.isEmpty()) {
|
if (!phases.isEmpty()) {
|
||||||
@@ -417,7 +496,7 @@ public class DefaultLifecycleProcessor implements LifecycleProcessor, BeanFactor
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// overridable hooks
|
// Overridable hooks
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieve all applicable Lifecycle beans: all singletons that have already been created,
|
* Retrieve all applicable Lifecycle beans: all singletons that have already been created,
|
||||||
@@ -473,8 +552,6 @@ public class DefaultLifecycleProcessor implements LifecycleProcessor, BeanFactor
|
|||||||
|
|
||||||
private final int phase;
|
private final int phase;
|
||||||
|
|
||||||
private final long timeout;
|
|
||||||
|
|
||||||
private final Map<String, ? extends Lifecycle> lifecycleBeans;
|
private final Map<String, ? extends Lifecycle> lifecycleBeans;
|
||||||
|
|
||||||
private final boolean autoStartupOnly;
|
private final boolean autoStartupOnly;
|
||||||
@@ -483,11 +560,8 @@ public class DefaultLifecycleProcessor implements LifecycleProcessor, BeanFactor
|
|||||||
|
|
||||||
private int smartMemberCount;
|
private int smartMemberCount;
|
||||||
|
|
||||||
public LifecycleGroup(
|
public LifecycleGroup(int phase, Map<String, ? extends Lifecycle> lifecycleBeans, boolean autoStartupOnly) {
|
||||||
int phase, long timeout, Map<String, ? extends Lifecycle> lifecycleBeans, boolean autoStartupOnly) {
|
|
||||||
|
|
||||||
this.phase = phase;
|
this.phase = phase;
|
||||||
this.timeout = timeout;
|
|
||||||
this.lifecycleBeans = lifecycleBeans;
|
this.lifecycleBeans = lifecycleBeans;
|
||||||
this.autoStartupOnly = autoStartupOnly;
|
this.autoStartupOnly = autoStartupOnly;
|
||||||
}
|
}
|
||||||
@@ -506,8 +580,26 @@ public class DefaultLifecycleProcessor implements LifecycleProcessor, BeanFactor
|
|||||||
if (logger.isDebugEnabled()) {
|
if (logger.isDebugEnabled()) {
|
||||||
logger.debug("Starting beans in phase " + this.phase);
|
logger.debug("Starting beans in phase " + this.phase);
|
||||||
}
|
}
|
||||||
|
Long concurrentStartup = determineConcurrentStartup(this.phase);
|
||||||
|
List<CompletableFuture<?>> futures = (concurrentStartup != null ? new ArrayList<>() : null);
|
||||||
for (LifecycleGroupMember member : this.members) {
|
for (LifecycleGroupMember member : this.members) {
|
||||||
doStart(this.lifecycleBeans, member.name, this.autoStartupOnly);
|
doStart(this.lifecycleBeans, member.name, this.autoStartupOnly, futures);
|
||||||
|
}
|
||||||
|
if (concurrentStartup != null && !CollectionUtils.isEmpty(futures)) {
|
||||||
|
try {
|
||||||
|
CompletableFuture.allOf(futures.toArray(new CompletableFuture<?>[0]))
|
||||||
|
.get(concurrentStartup, TimeUnit.MILLISECONDS);
|
||||||
|
}
|
||||||
|
catch (Exception ex) {
|
||||||
|
if (ex instanceof ExecutionException exEx) {
|
||||||
|
Throwable cause = exEx.getCause();
|
||||||
|
if (cause instanceof ApplicationContextException acEx) {
|
||||||
|
throw acEx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw new ApplicationContextException("Failed to start beans in phase " + this.phase +
|
||||||
|
" within timeout of " + concurrentStartup + "ms", ex);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -531,11 +623,14 @@ public class DefaultLifecycleProcessor implements LifecycleProcessor, BeanFactor
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
latch.await(this.timeout, TimeUnit.MILLISECONDS);
|
long shutdownTimeout = determineShutdownTimeout(this.phase);
|
||||||
if (latch.getCount() > 0 && !countDownBeanNames.isEmpty() && logger.isInfoEnabled()) {
|
if (!latch.await(shutdownTimeout, TimeUnit.MILLISECONDS)) {
|
||||||
logger.info("Shutdown phase " + this.phase + " ends with " + countDownBeanNames.size() +
|
// Count is still >0 after timeout
|
||||||
" bean" + (countDownBeanNames.size() > 1 ? "s" : "") +
|
if (!countDownBeanNames.isEmpty() && logger.isInfoEnabled()) {
|
||||||
" still running after timeout of " + this.timeout + "ms: " + countDownBeanNames);
|
logger.info("Shutdown phase " + this.phase + " ends with " + countDownBeanNames.size() +
|
||||||
|
" bean" + (countDownBeanNames.size() > 1 ? "s" : "") +
|
||||||
|
" still running after timeout of " + shutdownTimeout + "ms: " + countDownBeanNames);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (InterruptedException ex) {
|
catch (InterruptedException ex) {
|
||||||
|
|||||||
+64
-21
@@ -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");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -16,6 +16,7 @@
|
|||||||
|
|
||||||
package org.springframework.context.support;
|
package org.springframework.context.support;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
import java.util.concurrent.CopyOnWriteArrayList;
|
import java.util.concurrent.CopyOnWriteArrayList;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
@@ -30,6 +31,7 @@ import org.springframework.context.Lifecycle;
|
|||||||
import org.springframework.context.LifecycleProcessor;
|
import org.springframework.context.LifecycleProcessor;
|
||||||
import org.springframework.context.SmartLifecycle;
|
import org.springframework.context.SmartLifecycle;
|
||||||
import org.springframework.core.testfixture.EnabledForTestGroups;
|
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.assertThat;
|
||||||
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||||
@@ -54,10 +56,11 @@ class DefaultLifecycleProcessorTests {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
void customLifecycleProcessorInstance() {
|
void customLifecycleProcessorInstance() {
|
||||||
|
StaticApplicationContext context = new StaticApplicationContext();
|
||||||
BeanDefinition beanDefinition = new RootBeanDefinition(DefaultLifecycleProcessor.class);
|
BeanDefinition beanDefinition = new RootBeanDefinition(DefaultLifecycleProcessor.class);
|
||||||
beanDefinition.getPropertyValues().addPropertyValue("timeoutPerShutdownPhase", 1000);
|
beanDefinition.getPropertyValues().addPropertyValue("timeoutPerShutdownPhase", 1000);
|
||||||
StaticApplicationContext context = new StaticApplicationContext();
|
context.registerBeanDefinition(StaticApplicationContext.LIFECYCLE_PROCESSOR_BEAN_NAME, beanDefinition);
|
||||||
context.registerBeanDefinition("lifecycleProcessor", beanDefinition);
|
|
||||||
context.refresh();
|
context.refresh();
|
||||||
LifecycleProcessor bean = context.getBean("lifecycleProcessor", LifecycleProcessor.class);
|
LifecycleProcessor bean = context.getBean("lifecycleProcessor", LifecycleProcessor.class);
|
||||||
Object contextLifecycleProcessor = new DirectFieldAccessor(context).getPropertyValue("lifecycleProcessor");
|
Object contextLifecycleProcessor = new DirectFieldAccessor(context).getPropertyValue("lifecycleProcessor");
|
||||||
@@ -70,11 +73,12 @@ class DefaultLifecycleProcessorTests {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
void singleSmartLifecycleAutoStartup() {
|
void singleSmartLifecycleAutoStartup() {
|
||||||
|
StaticApplicationContext context = new StaticApplicationContext();
|
||||||
CopyOnWriteArrayList<Lifecycle> startedBeans = new CopyOnWriteArrayList<>();
|
CopyOnWriteArrayList<Lifecycle> startedBeans = new CopyOnWriteArrayList<>();
|
||||||
TestSmartLifecycleBean bean = TestSmartLifecycleBean.forStartupTests(1, startedBeans);
|
TestSmartLifecycleBean bean = TestSmartLifecycleBean.forStartupTests(1, startedBeans);
|
||||||
bean.setAutoStartup(true);
|
bean.setAutoStartup(true);
|
||||||
StaticApplicationContext context = new StaticApplicationContext();
|
|
||||||
context.getBeanFactory().registerSingleton("bean", bean);
|
context.getBeanFactory().registerSingleton("bean", bean);
|
||||||
|
|
||||||
assertThat(bean.isRunning()).isFalse();
|
assertThat(bean.isRunning()).isFalse();
|
||||||
context.refresh();
|
context.refresh();
|
||||||
assertThat(bean.isRunning()).isTrue();
|
assertThat(bean.isRunning()).isTrue();
|
||||||
@@ -114,12 +118,13 @@ class DefaultLifecycleProcessorTests {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
void singleSmartLifecycleAutoStartupWithFailingLifecycleBean() {
|
void singleSmartLifecycleAutoStartupWithFailingLifecycleBean() {
|
||||||
|
StaticApplicationContext context = new StaticApplicationContext();
|
||||||
CopyOnWriteArrayList<Lifecycle> startedBeans = new CopyOnWriteArrayList<>();
|
CopyOnWriteArrayList<Lifecycle> startedBeans = new CopyOnWriteArrayList<>();
|
||||||
TestSmartLifecycleBean bean = TestSmartLifecycleBean.forStartupTests(1, startedBeans);
|
TestSmartLifecycleBean bean = TestSmartLifecycleBean.forStartupTests(1, startedBeans);
|
||||||
bean.setAutoStartup(true);
|
bean.setAutoStartup(true);
|
||||||
StaticApplicationContext context = new StaticApplicationContext();
|
|
||||||
context.getBeanFactory().registerSingleton("bean", bean);
|
context.getBeanFactory().registerSingleton("bean", bean);
|
||||||
context.registerSingleton("failingBean", FailingLifecycleBean.class);
|
context.registerSingleton("failingBean", FailingLifecycleBean.class);
|
||||||
|
|
||||||
assertThat(bean.isRunning()).isFalse();
|
assertThat(bean.isRunning()).isFalse();
|
||||||
assertThatExceptionOfType(ApplicationContextException.class)
|
assertThatExceptionOfType(ApplicationContextException.class)
|
||||||
.isThrownBy(context::refresh).withCauseInstanceOf(IllegalStateException.class);
|
.isThrownBy(context::refresh).withCauseInstanceOf(IllegalStateException.class);
|
||||||
@@ -130,11 +135,12 @@ class DefaultLifecycleProcessorTests {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
void singleSmartLifecycleWithoutAutoStartup() {
|
void singleSmartLifecycleWithoutAutoStartup() {
|
||||||
|
StaticApplicationContext context = new StaticApplicationContext();
|
||||||
CopyOnWriteArrayList<Lifecycle> startedBeans = new CopyOnWriteArrayList<>();
|
CopyOnWriteArrayList<Lifecycle> startedBeans = new CopyOnWriteArrayList<>();
|
||||||
TestSmartLifecycleBean bean = TestSmartLifecycleBean.forStartupTests(1, startedBeans);
|
TestSmartLifecycleBean bean = TestSmartLifecycleBean.forStartupTests(1, startedBeans);
|
||||||
bean.setAutoStartup(false);
|
bean.setAutoStartup(false);
|
||||||
StaticApplicationContext context = new StaticApplicationContext();
|
|
||||||
context.getBeanFactory().registerSingleton("bean", bean);
|
context.getBeanFactory().registerSingleton("bean", bean);
|
||||||
|
|
||||||
assertThat(bean.isRunning()).isFalse();
|
assertThat(bean.isRunning()).isFalse();
|
||||||
context.refresh();
|
context.refresh();
|
||||||
assertThat(bean.isRunning()).isFalse();
|
assertThat(bean.isRunning()).isFalse();
|
||||||
@@ -148,15 +154,16 @@ class DefaultLifecycleProcessorTests {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
void singleSmartLifecycleAutoStartupWithNonAutoStartupDependency() {
|
void singleSmartLifecycleAutoStartupWithNonAutoStartupDependency() {
|
||||||
|
StaticApplicationContext context = new StaticApplicationContext();
|
||||||
CopyOnWriteArrayList<Lifecycle> startedBeans = new CopyOnWriteArrayList<>();
|
CopyOnWriteArrayList<Lifecycle> startedBeans = new CopyOnWriteArrayList<>();
|
||||||
TestSmartLifecycleBean bean = TestSmartLifecycleBean.forStartupTests(1, startedBeans);
|
TestSmartLifecycleBean bean = TestSmartLifecycleBean.forStartupTests(1, startedBeans);
|
||||||
bean.setAutoStartup(true);
|
bean.setAutoStartup(true);
|
||||||
TestSmartLifecycleBean dependency = TestSmartLifecycleBean.forStartupTests(1, startedBeans);
|
TestSmartLifecycleBean dependency = TestSmartLifecycleBean.forStartupTests(1, startedBeans);
|
||||||
dependency.setAutoStartup(false);
|
dependency.setAutoStartup(false);
|
||||||
StaticApplicationContext context = new StaticApplicationContext();
|
|
||||||
context.getBeanFactory().registerSingleton("bean", bean);
|
context.getBeanFactory().registerSingleton("bean", bean);
|
||||||
context.getBeanFactory().registerSingleton("dependency", dependency);
|
context.getBeanFactory().registerSingleton("dependency", dependency);
|
||||||
context.getBeanFactory().registerDependentBean("dependency", "bean");
|
context.getBeanFactory().registerDependentBean("dependency", "bean");
|
||||||
|
|
||||||
assertThat(bean.isRunning()).isFalse();
|
assertThat(bean.isRunning()).isFalse();
|
||||||
assertThat(dependency.isRunning()).isFalse();
|
assertThat(dependency.isRunning()).isFalse();
|
||||||
context.refresh();
|
context.refresh();
|
||||||
@@ -169,20 +176,42 @@ class DefaultLifecycleProcessorTests {
|
|||||||
context.close();
|
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
|
@Test
|
||||||
void smartLifecycleGroupStartup() {
|
void smartLifecycleGroupStartup() {
|
||||||
|
StaticApplicationContext context = new StaticApplicationContext();
|
||||||
CopyOnWriteArrayList<Lifecycle> startedBeans = new CopyOnWriteArrayList<>();
|
CopyOnWriteArrayList<Lifecycle> startedBeans = new CopyOnWriteArrayList<>();
|
||||||
TestSmartLifecycleBean beanMin = TestSmartLifecycleBean.forStartupTests(Integer.MIN_VALUE, startedBeans);
|
TestSmartLifecycleBean beanMin = TestSmartLifecycleBean.forStartupTests(Integer.MIN_VALUE, startedBeans);
|
||||||
TestSmartLifecycleBean bean1 = TestSmartLifecycleBean.forStartupTests(1, startedBeans);
|
TestSmartLifecycleBean bean1 = TestSmartLifecycleBean.forStartupTests(1, startedBeans);
|
||||||
TestSmartLifecycleBean bean2 = TestSmartLifecycleBean.forStartupTests(2, startedBeans);
|
TestSmartLifecycleBean bean2 = TestSmartLifecycleBean.forStartupTests(2, startedBeans);
|
||||||
TestSmartLifecycleBean bean3 = TestSmartLifecycleBean.forStartupTests(3, startedBeans);
|
TestSmartLifecycleBean bean3 = TestSmartLifecycleBean.forStartupTests(3, startedBeans);
|
||||||
TestSmartLifecycleBean beanMax = TestSmartLifecycleBean.forStartupTests(Integer.MAX_VALUE, startedBeans);
|
TestSmartLifecycleBean beanMax = TestSmartLifecycleBean.forStartupTests(Integer.MAX_VALUE, startedBeans);
|
||||||
StaticApplicationContext context = new StaticApplicationContext();
|
|
||||||
context.getBeanFactory().registerSingleton("bean3", bean3);
|
context.getBeanFactory().registerSingleton("bean3", bean3);
|
||||||
context.getBeanFactory().registerSingleton("beanMin", beanMin);
|
context.getBeanFactory().registerSingleton("beanMin", beanMin);
|
||||||
context.getBeanFactory().registerSingleton("bean2", bean2);
|
context.getBeanFactory().registerSingleton("bean2", bean2);
|
||||||
context.getBeanFactory().registerSingleton("beanMax", beanMax);
|
context.getBeanFactory().registerSingleton("beanMax", beanMax);
|
||||||
context.getBeanFactory().registerSingleton("bean1", bean1);
|
context.getBeanFactory().registerSingleton("bean1", bean1);
|
||||||
|
|
||||||
assertThat(beanMin.isRunning()).isFalse();
|
assertThat(beanMin.isRunning()).isFalse();
|
||||||
assertThat(bean1.isRunning()).isFalse();
|
assertThat(bean1.isRunning()).isFalse();
|
||||||
assertThat(bean2.isRunning()).isFalse();
|
assertThat(bean2.isRunning()).isFalse();
|
||||||
@@ -202,16 +231,17 @@ class DefaultLifecycleProcessorTests {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
void contextRefreshThenStartWithMixedBeans() {
|
void contextRefreshThenStartWithMixedBeans() {
|
||||||
|
StaticApplicationContext context = new StaticApplicationContext();
|
||||||
CopyOnWriteArrayList<Lifecycle> startedBeans = new CopyOnWriteArrayList<>();
|
CopyOnWriteArrayList<Lifecycle> startedBeans = new CopyOnWriteArrayList<>();
|
||||||
TestLifecycleBean simpleBean1 = TestLifecycleBean.forStartupTests(startedBeans);
|
TestLifecycleBean simpleBean1 = TestLifecycleBean.forStartupTests(startedBeans);
|
||||||
TestLifecycleBean simpleBean2 = TestLifecycleBean.forStartupTests(startedBeans);
|
TestLifecycleBean simpleBean2 = TestLifecycleBean.forStartupTests(startedBeans);
|
||||||
TestSmartLifecycleBean smartBean1 = TestSmartLifecycleBean.forStartupTests(5, startedBeans);
|
TestSmartLifecycleBean smartBean1 = TestSmartLifecycleBean.forStartupTests(5, startedBeans);
|
||||||
TestSmartLifecycleBean smartBean2 = TestSmartLifecycleBean.forStartupTests(-3, startedBeans);
|
TestSmartLifecycleBean smartBean2 = TestSmartLifecycleBean.forStartupTests(-3, startedBeans);
|
||||||
StaticApplicationContext context = new StaticApplicationContext();
|
|
||||||
context.getBeanFactory().registerSingleton("simpleBean1", simpleBean1);
|
context.getBeanFactory().registerSingleton("simpleBean1", simpleBean1);
|
||||||
context.getBeanFactory().registerSingleton("smartBean1", smartBean1);
|
context.getBeanFactory().registerSingleton("smartBean1", smartBean1);
|
||||||
context.getBeanFactory().registerSingleton("simpleBean2", simpleBean2);
|
context.getBeanFactory().registerSingleton("simpleBean2", simpleBean2);
|
||||||
context.getBeanFactory().registerSingleton("smartBean2", smartBean2);
|
context.getBeanFactory().registerSingleton("smartBean2", smartBean2);
|
||||||
|
|
||||||
assertThat(simpleBean1.isRunning()).isFalse();
|
assertThat(simpleBean1.isRunning()).isFalse();
|
||||||
assertThat(simpleBean2.isRunning()).isFalse();
|
assertThat(simpleBean2.isRunning()).isFalse();
|
||||||
assertThat(smartBean1.isRunning()).isFalse();
|
assertThat(smartBean1.isRunning()).isFalse();
|
||||||
@@ -233,16 +263,17 @@ class DefaultLifecycleProcessorTests {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
void contextRefreshThenStopAndRestartWithMixedBeans() {
|
void contextRefreshThenStopAndRestartWithMixedBeans() {
|
||||||
|
StaticApplicationContext context = new StaticApplicationContext();
|
||||||
CopyOnWriteArrayList<Lifecycle> startedBeans = new CopyOnWriteArrayList<>();
|
CopyOnWriteArrayList<Lifecycle> startedBeans = new CopyOnWriteArrayList<>();
|
||||||
TestLifecycleBean simpleBean1 = TestLifecycleBean.forStartupTests(startedBeans);
|
TestLifecycleBean simpleBean1 = TestLifecycleBean.forStartupTests(startedBeans);
|
||||||
TestLifecycleBean simpleBean2 = TestLifecycleBean.forStartupTests(startedBeans);
|
TestLifecycleBean simpleBean2 = TestLifecycleBean.forStartupTests(startedBeans);
|
||||||
TestSmartLifecycleBean smartBean1 = TestSmartLifecycleBean.forStartupTests(5, startedBeans);
|
TestSmartLifecycleBean smartBean1 = TestSmartLifecycleBean.forStartupTests(5, startedBeans);
|
||||||
TestSmartLifecycleBean smartBean2 = TestSmartLifecycleBean.forStartupTests(-3, startedBeans);
|
TestSmartLifecycleBean smartBean2 = TestSmartLifecycleBean.forStartupTests(-3, startedBeans);
|
||||||
StaticApplicationContext context = new StaticApplicationContext();
|
|
||||||
context.getBeanFactory().registerSingleton("simpleBean1", simpleBean1);
|
context.getBeanFactory().registerSingleton("simpleBean1", simpleBean1);
|
||||||
context.getBeanFactory().registerSingleton("smartBean1", smartBean1);
|
context.getBeanFactory().registerSingleton("smartBean1", smartBean1);
|
||||||
context.getBeanFactory().registerSingleton("simpleBean2", simpleBean2);
|
context.getBeanFactory().registerSingleton("simpleBean2", simpleBean2);
|
||||||
context.getBeanFactory().registerSingleton("smartBean2", smartBean2);
|
context.getBeanFactory().registerSingleton("smartBean2", smartBean2);
|
||||||
|
|
||||||
assertThat(simpleBean1.isRunning()).isFalse();
|
assertThat(simpleBean1.isRunning()).isFalse();
|
||||||
assertThat(simpleBean2.isRunning()).isFalse();
|
assertThat(simpleBean2.isRunning()).isFalse();
|
||||||
assertThat(smartBean1.isRunning()).isFalse();
|
assertThat(smartBean1.isRunning()).isFalse();
|
||||||
@@ -270,16 +301,17 @@ class DefaultLifecycleProcessorTests {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
void contextRefreshThenStopForRestartWithMixedBeans() {
|
void contextRefreshThenStopForRestartWithMixedBeans() {
|
||||||
|
StaticApplicationContext context = new StaticApplicationContext();
|
||||||
CopyOnWriteArrayList<Lifecycle> startedBeans = new CopyOnWriteArrayList<>();
|
CopyOnWriteArrayList<Lifecycle> startedBeans = new CopyOnWriteArrayList<>();
|
||||||
TestLifecycleBean simpleBean1 = TestLifecycleBean.forStartupTests(startedBeans);
|
TestLifecycleBean simpleBean1 = TestLifecycleBean.forStartupTests(startedBeans);
|
||||||
TestLifecycleBean simpleBean2 = TestLifecycleBean.forStartupTests(startedBeans);
|
TestLifecycleBean simpleBean2 = TestLifecycleBean.forStartupTests(startedBeans);
|
||||||
TestSmartLifecycleBean smartBean1 = TestSmartLifecycleBean.forStartupTests(5, startedBeans);
|
TestSmartLifecycleBean smartBean1 = TestSmartLifecycleBean.forStartupTests(5, startedBeans);
|
||||||
TestSmartLifecycleBean smartBean2 = TestSmartLifecycleBean.forStartupTests(-3, startedBeans);
|
TestSmartLifecycleBean smartBean2 = TestSmartLifecycleBean.forStartupTests(-3, startedBeans);
|
||||||
StaticApplicationContext context = new StaticApplicationContext();
|
|
||||||
context.getBeanFactory().registerSingleton("simpleBean1", simpleBean1);
|
context.getBeanFactory().registerSingleton("simpleBean1", simpleBean1);
|
||||||
context.getBeanFactory().registerSingleton("smartBean1", smartBean1);
|
context.getBeanFactory().registerSingleton("smartBean1", smartBean1);
|
||||||
context.getBeanFactory().registerSingleton("simpleBean2", simpleBean2);
|
context.getBeanFactory().registerSingleton("simpleBean2", simpleBean2);
|
||||||
context.getBeanFactory().registerSingleton("smartBean2", smartBean2);
|
context.getBeanFactory().registerSingleton("smartBean2", smartBean2);
|
||||||
|
|
||||||
assertThat(simpleBean1.isRunning()).isFalse();
|
assertThat(simpleBean1.isRunning()).isFalse();
|
||||||
assertThat(simpleBean2.isRunning()).isFalse();
|
assertThat(simpleBean2.isRunning()).isFalse();
|
||||||
assertThat(smartBean1.isRunning()).isFalse();
|
assertThat(smartBean1.isRunning()).isFalse();
|
||||||
@@ -319,6 +351,7 @@ class DefaultLifecycleProcessorTests {
|
|||||||
@Test
|
@Test
|
||||||
@EnabledForTestGroups(LONG_RUNNING)
|
@EnabledForTestGroups(LONG_RUNNING)
|
||||||
void smartLifecycleGroupShutdown() {
|
void smartLifecycleGroupShutdown() {
|
||||||
|
StaticApplicationContext context = new StaticApplicationContext();
|
||||||
CopyOnWriteArrayList<Lifecycle> stoppedBeans = new CopyOnWriteArrayList<>();
|
CopyOnWriteArrayList<Lifecycle> stoppedBeans = new CopyOnWriteArrayList<>();
|
||||||
TestSmartLifecycleBean bean1 = TestSmartLifecycleBean.forShutdownTests(1, 300, stoppedBeans);
|
TestSmartLifecycleBean bean1 = TestSmartLifecycleBean.forShutdownTests(1, 300, stoppedBeans);
|
||||||
TestSmartLifecycleBean bean2 = TestSmartLifecycleBean.forShutdownTests(3, 100, stoppedBeans);
|
TestSmartLifecycleBean bean2 = TestSmartLifecycleBean.forShutdownTests(3, 100, stoppedBeans);
|
||||||
@@ -327,7 +360,6 @@ class DefaultLifecycleProcessorTests {
|
|||||||
TestSmartLifecycleBean bean5 = TestSmartLifecycleBean.forShutdownTests(2, 700, stoppedBeans);
|
TestSmartLifecycleBean bean5 = TestSmartLifecycleBean.forShutdownTests(2, 700, stoppedBeans);
|
||||||
TestSmartLifecycleBean bean6 = TestSmartLifecycleBean.forShutdownTests(Integer.MAX_VALUE, 200, stoppedBeans);
|
TestSmartLifecycleBean bean6 = TestSmartLifecycleBean.forShutdownTests(Integer.MAX_VALUE, 200, stoppedBeans);
|
||||||
TestSmartLifecycleBean bean7 = TestSmartLifecycleBean.forShutdownTests(3, 200, stoppedBeans);
|
TestSmartLifecycleBean bean7 = TestSmartLifecycleBean.forShutdownTests(3, 200, stoppedBeans);
|
||||||
StaticApplicationContext context = new StaticApplicationContext();
|
|
||||||
context.getBeanFactory().registerSingleton("bean1", bean1);
|
context.getBeanFactory().registerSingleton("bean1", bean1);
|
||||||
context.getBeanFactory().registerSingleton("bean2", bean2);
|
context.getBeanFactory().registerSingleton("bean2", bean2);
|
||||||
context.getBeanFactory().registerSingleton("bean3", bean3);
|
context.getBeanFactory().registerSingleton("bean3", bean3);
|
||||||
@@ -335,6 +367,7 @@ class DefaultLifecycleProcessorTests {
|
|||||||
context.getBeanFactory().registerSingleton("bean5", bean5);
|
context.getBeanFactory().registerSingleton("bean5", bean5);
|
||||||
context.getBeanFactory().registerSingleton("bean6", bean6);
|
context.getBeanFactory().registerSingleton("bean6", bean6);
|
||||||
context.getBeanFactory().registerSingleton("bean7", bean7);
|
context.getBeanFactory().registerSingleton("bean7", bean7);
|
||||||
|
|
||||||
context.refresh();
|
context.refresh();
|
||||||
context.stop();
|
context.stop();
|
||||||
assertThat(stoppedBeans).satisfiesExactly(hasPhase(Integer.MAX_VALUE), hasPhase(3),
|
assertThat(stoppedBeans).satisfiesExactly(hasPhase(Integer.MAX_VALUE), hasPhase(3),
|
||||||
@@ -345,11 +378,12 @@ class DefaultLifecycleProcessorTests {
|
|||||||
@Test
|
@Test
|
||||||
@EnabledForTestGroups(LONG_RUNNING)
|
@EnabledForTestGroups(LONG_RUNNING)
|
||||||
void singleSmartLifecycleShutdown() {
|
void singleSmartLifecycleShutdown() {
|
||||||
|
StaticApplicationContext context = new StaticApplicationContext();
|
||||||
CopyOnWriteArrayList<Lifecycle> stoppedBeans = new CopyOnWriteArrayList<>();
|
CopyOnWriteArrayList<Lifecycle> stoppedBeans = new CopyOnWriteArrayList<>();
|
||||||
TestSmartLifecycleBean bean = TestSmartLifecycleBean.forShutdownTests(99, 300, stoppedBeans);
|
TestSmartLifecycleBean bean = TestSmartLifecycleBean.forShutdownTests(99, 300, stoppedBeans);
|
||||||
StaticApplicationContext context = new StaticApplicationContext();
|
|
||||||
context.getBeanFactory().registerSingleton("bean", bean);
|
context.getBeanFactory().registerSingleton("bean", bean);
|
||||||
context.refresh();
|
context.refresh();
|
||||||
|
|
||||||
assertThat(bean.isRunning()).isTrue();
|
assertThat(bean.isRunning()).isTrue();
|
||||||
context.stop();
|
context.stop();
|
||||||
assertThat(bean.isRunning()).isFalse();
|
assertThat(bean.isRunning()).isFalse();
|
||||||
@@ -359,10 +393,11 @@ class DefaultLifecycleProcessorTests {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
void singleLifecycleShutdown() {
|
void singleLifecycleShutdown() {
|
||||||
|
StaticApplicationContext context = new StaticApplicationContext();
|
||||||
CopyOnWriteArrayList<Lifecycle> stoppedBeans = new CopyOnWriteArrayList<>();
|
CopyOnWriteArrayList<Lifecycle> stoppedBeans = new CopyOnWriteArrayList<>();
|
||||||
Lifecycle bean = new TestLifecycleBean(null, stoppedBeans);
|
Lifecycle bean = new TestLifecycleBean(null, stoppedBeans);
|
||||||
StaticApplicationContext context = new StaticApplicationContext();
|
|
||||||
context.getBeanFactory().registerSingleton("bean", bean);
|
context.getBeanFactory().registerSingleton("bean", bean);
|
||||||
|
|
||||||
context.refresh();
|
context.refresh();
|
||||||
assertThat(bean.isRunning()).isFalse();
|
assertThat(bean.isRunning()).isFalse();
|
||||||
bean.start();
|
bean.start();
|
||||||
@@ -375,6 +410,7 @@ class DefaultLifecycleProcessorTests {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
void mixedShutdown() {
|
void mixedShutdown() {
|
||||||
|
StaticApplicationContext context = new StaticApplicationContext();
|
||||||
CopyOnWriteArrayList<Lifecycle> stoppedBeans = new CopyOnWriteArrayList<>();
|
CopyOnWriteArrayList<Lifecycle> stoppedBeans = new CopyOnWriteArrayList<>();
|
||||||
Lifecycle bean1 = TestLifecycleBean.forShutdownTests(stoppedBeans);
|
Lifecycle bean1 = TestLifecycleBean.forShutdownTests(stoppedBeans);
|
||||||
Lifecycle bean2 = TestSmartLifecycleBean.forShutdownTests(500, 200, stoppedBeans);
|
Lifecycle bean2 = TestSmartLifecycleBean.forShutdownTests(500, 200, stoppedBeans);
|
||||||
@@ -383,7 +419,6 @@ class DefaultLifecycleProcessorTests {
|
|||||||
Lifecycle bean5 = TestSmartLifecycleBean.forShutdownTests(1, 200, stoppedBeans);
|
Lifecycle bean5 = TestSmartLifecycleBean.forShutdownTests(1, 200, stoppedBeans);
|
||||||
Lifecycle bean6 = TestSmartLifecycleBean.forShutdownTests(-1, 100, stoppedBeans);
|
Lifecycle bean6 = TestSmartLifecycleBean.forShutdownTests(-1, 100, stoppedBeans);
|
||||||
Lifecycle bean7 = TestSmartLifecycleBean.forShutdownTests(Integer.MIN_VALUE, 300, stoppedBeans);
|
Lifecycle bean7 = TestSmartLifecycleBean.forShutdownTests(Integer.MIN_VALUE, 300, stoppedBeans);
|
||||||
StaticApplicationContext context = new StaticApplicationContext();
|
|
||||||
context.getBeanFactory().registerSingleton("bean1", bean1);
|
context.getBeanFactory().registerSingleton("bean1", bean1);
|
||||||
context.getBeanFactory().registerSingleton("bean2", bean2);
|
context.getBeanFactory().registerSingleton("bean2", bean2);
|
||||||
context.getBeanFactory().registerSingleton("bean3", bean3);
|
context.getBeanFactory().registerSingleton("bean3", bean3);
|
||||||
@@ -391,6 +426,7 @@ class DefaultLifecycleProcessorTests {
|
|||||||
context.getBeanFactory().registerSingleton("bean5", bean5);
|
context.getBeanFactory().registerSingleton("bean5", bean5);
|
||||||
context.getBeanFactory().registerSingleton("bean6", bean6);
|
context.getBeanFactory().registerSingleton("bean6", bean6);
|
||||||
context.getBeanFactory().registerSingleton("bean7", bean7);
|
context.getBeanFactory().registerSingleton("bean7", bean7);
|
||||||
|
|
||||||
context.refresh();
|
context.refresh();
|
||||||
assertThat(bean2.isRunning()).isTrue();
|
assertThat(bean2.isRunning()).isTrue();
|
||||||
assertThat(bean3.isRunning()).isTrue();
|
assertThat(bean3.isRunning()).isTrue();
|
||||||
@@ -418,17 +454,18 @@ class DefaultLifecycleProcessorTests {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
void dependencyStartedFirstEvenIfItsPhaseIsHigher() {
|
void dependencyStartedFirstEvenIfItsPhaseIsHigher() {
|
||||||
|
StaticApplicationContext context = new StaticApplicationContext();
|
||||||
CopyOnWriteArrayList<Lifecycle> startedBeans = new CopyOnWriteArrayList<>();
|
CopyOnWriteArrayList<Lifecycle> startedBeans = new CopyOnWriteArrayList<>();
|
||||||
TestSmartLifecycleBean beanMin = TestSmartLifecycleBean.forStartupTests(Integer.MIN_VALUE, startedBeans);
|
TestSmartLifecycleBean beanMin = TestSmartLifecycleBean.forStartupTests(Integer.MIN_VALUE, startedBeans);
|
||||||
TestSmartLifecycleBean bean2 = TestSmartLifecycleBean.forStartupTests(2, startedBeans);
|
TestSmartLifecycleBean bean2 = TestSmartLifecycleBean.forStartupTests(2, startedBeans);
|
||||||
TestSmartLifecycleBean bean99 = TestSmartLifecycleBean.forStartupTests(99, startedBeans);
|
TestSmartLifecycleBean bean99 = TestSmartLifecycleBean.forStartupTests(99, startedBeans);
|
||||||
TestSmartLifecycleBean beanMax = TestSmartLifecycleBean.forStartupTests(Integer.MAX_VALUE, startedBeans);
|
TestSmartLifecycleBean beanMax = TestSmartLifecycleBean.forStartupTests(Integer.MAX_VALUE, startedBeans);
|
||||||
StaticApplicationContext context = new StaticApplicationContext();
|
|
||||||
context.getBeanFactory().registerSingleton("beanMin", beanMin);
|
context.getBeanFactory().registerSingleton("beanMin", beanMin);
|
||||||
context.getBeanFactory().registerSingleton("bean2", bean2);
|
context.getBeanFactory().registerSingleton("bean2", bean2);
|
||||||
context.getBeanFactory().registerSingleton("bean99", bean99);
|
context.getBeanFactory().registerSingleton("bean99", bean99);
|
||||||
context.getBeanFactory().registerSingleton("beanMax", beanMax);
|
context.getBeanFactory().registerSingleton("beanMax", beanMax);
|
||||||
context.getBeanFactory().registerDependentBean("bean99", "bean2");
|
context.getBeanFactory().registerDependentBean("bean99", "bean2");
|
||||||
|
|
||||||
context.refresh();
|
context.refresh();
|
||||||
assertThat(beanMin.isRunning()).isTrue();
|
assertThat(beanMin.isRunning()).isTrue();
|
||||||
assertThat(bean2.isRunning()).isTrue();
|
assertThat(bean2.isRunning()).isTrue();
|
||||||
@@ -446,6 +483,7 @@ class DefaultLifecycleProcessorTests {
|
|||||||
@Test
|
@Test
|
||||||
@EnabledForTestGroups(LONG_RUNNING)
|
@EnabledForTestGroups(LONG_RUNNING)
|
||||||
void dependentShutdownFirstEvenIfItsPhaseIsLower() {
|
void dependentShutdownFirstEvenIfItsPhaseIsLower() {
|
||||||
|
StaticApplicationContext context = new StaticApplicationContext();
|
||||||
CopyOnWriteArrayList<Lifecycle> stoppedBeans = new CopyOnWriteArrayList<>();
|
CopyOnWriteArrayList<Lifecycle> stoppedBeans = new CopyOnWriteArrayList<>();
|
||||||
TestSmartLifecycleBean beanMin = TestSmartLifecycleBean.forShutdownTests(Integer.MIN_VALUE, 100, stoppedBeans);
|
TestSmartLifecycleBean beanMin = TestSmartLifecycleBean.forShutdownTests(Integer.MIN_VALUE, 100, stoppedBeans);
|
||||||
TestSmartLifecycleBean bean1 = TestSmartLifecycleBean.forShutdownTests(1, 200, stoppedBeans);
|
TestSmartLifecycleBean bean1 = TestSmartLifecycleBean.forShutdownTests(1, 200, stoppedBeans);
|
||||||
@@ -453,7 +491,6 @@ class DefaultLifecycleProcessorTests {
|
|||||||
TestSmartLifecycleBean bean2 = TestSmartLifecycleBean.forShutdownTests(2, 300, stoppedBeans);
|
TestSmartLifecycleBean bean2 = TestSmartLifecycleBean.forShutdownTests(2, 300, stoppedBeans);
|
||||||
TestSmartLifecycleBean bean7 = TestSmartLifecycleBean.forShutdownTests(7, 400, stoppedBeans);
|
TestSmartLifecycleBean bean7 = TestSmartLifecycleBean.forShutdownTests(7, 400, stoppedBeans);
|
||||||
TestSmartLifecycleBean beanMax = TestSmartLifecycleBean.forShutdownTests(Integer.MAX_VALUE, 400, stoppedBeans);
|
TestSmartLifecycleBean beanMax = TestSmartLifecycleBean.forShutdownTests(Integer.MAX_VALUE, 400, stoppedBeans);
|
||||||
StaticApplicationContext context = new StaticApplicationContext();
|
|
||||||
context.getBeanFactory().registerSingleton("beanMin", beanMin);
|
context.getBeanFactory().registerSingleton("beanMin", beanMin);
|
||||||
context.getBeanFactory().registerSingleton("bean1", bean1);
|
context.getBeanFactory().registerSingleton("bean1", bean1);
|
||||||
context.getBeanFactory().registerSingleton("bean2", bean2);
|
context.getBeanFactory().registerSingleton("bean2", bean2);
|
||||||
@@ -461,6 +498,7 @@ class DefaultLifecycleProcessorTests {
|
|||||||
context.getBeanFactory().registerSingleton("bean99", bean99);
|
context.getBeanFactory().registerSingleton("bean99", bean99);
|
||||||
context.getBeanFactory().registerSingleton("beanMax", beanMax);
|
context.getBeanFactory().registerSingleton("beanMax", beanMax);
|
||||||
context.getBeanFactory().registerDependentBean("bean99", "bean2");
|
context.getBeanFactory().registerDependentBean("bean99", "bean2");
|
||||||
|
|
||||||
context.refresh();
|
context.refresh();
|
||||||
assertThat(beanMin.isRunning()).isTrue();
|
assertThat(beanMin.isRunning()).isTrue();
|
||||||
assertThat(bean1.isRunning()).isTrue();
|
assertThat(bean1.isRunning()).isTrue();
|
||||||
@@ -486,17 +524,18 @@ class DefaultLifecycleProcessorTests {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
void dependencyStartedFirstAndIsSmartLifecycle() {
|
void dependencyStartedFirstAndIsSmartLifecycle() {
|
||||||
|
StaticApplicationContext context = new StaticApplicationContext();
|
||||||
CopyOnWriteArrayList<Lifecycle> startedBeans = new CopyOnWriteArrayList<>();
|
CopyOnWriteArrayList<Lifecycle> startedBeans = new CopyOnWriteArrayList<>();
|
||||||
TestSmartLifecycleBean beanNegative = TestSmartLifecycleBean.forStartupTests(-99, startedBeans);
|
TestSmartLifecycleBean beanNegative = TestSmartLifecycleBean.forStartupTests(-99, startedBeans);
|
||||||
TestSmartLifecycleBean bean99 = TestSmartLifecycleBean.forStartupTests(99, startedBeans);
|
TestSmartLifecycleBean bean99 = TestSmartLifecycleBean.forStartupTests(99, startedBeans);
|
||||||
TestSmartLifecycleBean bean7 = TestSmartLifecycleBean.forStartupTests(7, startedBeans);
|
TestSmartLifecycleBean bean7 = TestSmartLifecycleBean.forStartupTests(7, startedBeans);
|
||||||
TestLifecycleBean simpleBean = TestLifecycleBean.forStartupTests(startedBeans);
|
TestLifecycleBean simpleBean = TestLifecycleBean.forStartupTests(startedBeans);
|
||||||
StaticApplicationContext context = new StaticApplicationContext();
|
|
||||||
context.getBeanFactory().registerSingleton("beanNegative", beanNegative);
|
context.getBeanFactory().registerSingleton("beanNegative", beanNegative);
|
||||||
context.getBeanFactory().registerSingleton("bean7", bean7);
|
context.getBeanFactory().registerSingleton("bean7", bean7);
|
||||||
context.getBeanFactory().registerSingleton("bean99", bean99);
|
context.getBeanFactory().registerSingleton("bean99", bean99);
|
||||||
context.getBeanFactory().registerSingleton("simpleBean", simpleBean);
|
context.getBeanFactory().registerSingleton("simpleBean", simpleBean);
|
||||||
context.getBeanFactory().registerDependentBean("bean7", "simpleBean");
|
context.getBeanFactory().registerDependentBean("bean7", "simpleBean");
|
||||||
|
|
||||||
context.refresh();
|
context.refresh();
|
||||||
context.stop();
|
context.stop();
|
||||||
startedBeans.clear();
|
startedBeans.clear();
|
||||||
@@ -514,6 +553,7 @@ class DefaultLifecycleProcessorTests {
|
|||||||
@Test
|
@Test
|
||||||
@EnabledForTestGroups(LONG_RUNNING)
|
@EnabledForTestGroups(LONG_RUNNING)
|
||||||
void dependentShutdownFirstAndIsSmartLifecycle() {
|
void dependentShutdownFirstAndIsSmartLifecycle() {
|
||||||
|
StaticApplicationContext context = new StaticApplicationContext();
|
||||||
CopyOnWriteArrayList<Lifecycle> stoppedBeans = new CopyOnWriteArrayList<>();
|
CopyOnWriteArrayList<Lifecycle> stoppedBeans = new CopyOnWriteArrayList<>();
|
||||||
TestSmartLifecycleBean beanMin = TestSmartLifecycleBean.forShutdownTests(Integer.MIN_VALUE, 400, stoppedBeans);
|
TestSmartLifecycleBean beanMin = TestSmartLifecycleBean.forShutdownTests(Integer.MIN_VALUE, 400, stoppedBeans);
|
||||||
TestSmartLifecycleBean beanNegative = TestSmartLifecycleBean.forShutdownTests(-99, 100, stoppedBeans);
|
TestSmartLifecycleBean beanNegative = TestSmartLifecycleBean.forShutdownTests(-99, 100, stoppedBeans);
|
||||||
@@ -521,7 +561,6 @@ class DefaultLifecycleProcessorTests {
|
|||||||
TestSmartLifecycleBean bean2 = TestSmartLifecycleBean.forShutdownTests(2, 300, stoppedBeans);
|
TestSmartLifecycleBean bean2 = TestSmartLifecycleBean.forShutdownTests(2, 300, stoppedBeans);
|
||||||
TestSmartLifecycleBean bean7 = TestSmartLifecycleBean.forShutdownTests(7, 400, stoppedBeans);
|
TestSmartLifecycleBean bean7 = TestSmartLifecycleBean.forShutdownTests(7, 400, stoppedBeans);
|
||||||
TestLifecycleBean simpleBean = TestLifecycleBean.forShutdownTests(stoppedBeans);
|
TestLifecycleBean simpleBean = TestLifecycleBean.forShutdownTests(stoppedBeans);
|
||||||
StaticApplicationContext context = new StaticApplicationContext();
|
|
||||||
context.getBeanFactory().registerSingleton("beanMin", beanMin);
|
context.getBeanFactory().registerSingleton("beanMin", beanMin);
|
||||||
context.getBeanFactory().registerSingleton("beanNegative", beanNegative);
|
context.getBeanFactory().registerSingleton("beanNegative", beanNegative);
|
||||||
context.getBeanFactory().registerSingleton("bean1", bean1);
|
context.getBeanFactory().registerSingleton("bean1", bean1);
|
||||||
@@ -529,6 +568,7 @@ class DefaultLifecycleProcessorTests {
|
|||||||
context.getBeanFactory().registerSingleton("bean7", bean7);
|
context.getBeanFactory().registerSingleton("bean7", bean7);
|
||||||
context.getBeanFactory().registerSingleton("simpleBean", simpleBean);
|
context.getBeanFactory().registerSingleton("simpleBean", simpleBean);
|
||||||
context.getBeanFactory().registerDependentBean("simpleBean", "beanNegative");
|
context.getBeanFactory().registerDependentBean("simpleBean", "beanNegative");
|
||||||
|
|
||||||
context.refresh();
|
context.refresh();
|
||||||
assertThat(beanMin.isRunning()).isTrue();
|
assertThat(beanMin.isRunning()).isTrue();
|
||||||
assertThat(beanNegative.isRunning()).isTrue();
|
assertThat(beanNegative.isRunning()).isTrue();
|
||||||
@@ -551,15 +591,16 @@ class DefaultLifecycleProcessorTests {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
void dependencyStartedFirstButNotSmartLifecycle() {
|
void dependencyStartedFirstButNotSmartLifecycle() {
|
||||||
|
StaticApplicationContext context = new StaticApplicationContext();
|
||||||
CopyOnWriteArrayList<Lifecycle> startedBeans = new CopyOnWriteArrayList<>();
|
CopyOnWriteArrayList<Lifecycle> startedBeans = new CopyOnWriteArrayList<>();
|
||||||
TestSmartLifecycleBean beanMin = TestSmartLifecycleBean.forStartupTests(Integer.MIN_VALUE, startedBeans);
|
TestSmartLifecycleBean beanMin = TestSmartLifecycleBean.forStartupTests(Integer.MIN_VALUE, startedBeans);
|
||||||
TestSmartLifecycleBean bean7 = TestSmartLifecycleBean.forStartupTests(7, startedBeans);
|
TestSmartLifecycleBean bean7 = TestSmartLifecycleBean.forStartupTests(7, startedBeans);
|
||||||
TestLifecycleBean simpleBean = TestLifecycleBean.forStartupTests(startedBeans);
|
TestLifecycleBean simpleBean = TestLifecycleBean.forStartupTests(startedBeans);
|
||||||
StaticApplicationContext context = new StaticApplicationContext();
|
|
||||||
context.getBeanFactory().registerSingleton("beanMin", beanMin);
|
context.getBeanFactory().registerSingleton("beanMin", beanMin);
|
||||||
context.getBeanFactory().registerSingleton("bean7", bean7);
|
context.getBeanFactory().registerSingleton("bean7", bean7);
|
||||||
context.getBeanFactory().registerSingleton("simpleBean", simpleBean);
|
context.getBeanFactory().registerSingleton("simpleBean", simpleBean);
|
||||||
context.getBeanFactory().registerDependentBean("simpleBean", "beanMin");
|
context.getBeanFactory().registerDependentBean("simpleBean", "beanMin");
|
||||||
|
|
||||||
context.refresh();
|
context.refresh();
|
||||||
assertThat(beanMin.isRunning()).isTrue();
|
assertThat(beanMin.isRunning()).isTrue();
|
||||||
assertThat(bean7.isRunning()).isTrue();
|
assertThat(bean7.isRunning()).isTrue();
|
||||||
@@ -572,19 +613,20 @@ class DefaultLifecycleProcessorTests {
|
|||||||
@Test
|
@Test
|
||||||
@EnabledForTestGroups(LONG_RUNNING)
|
@EnabledForTestGroups(LONG_RUNNING)
|
||||||
void dependentShutdownFirstButNotSmartLifecycle() {
|
void dependentShutdownFirstButNotSmartLifecycle() {
|
||||||
|
StaticApplicationContext context = new StaticApplicationContext();
|
||||||
CopyOnWriteArrayList<Lifecycle> stoppedBeans = new CopyOnWriteArrayList<>();
|
CopyOnWriteArrayList<Lifecycle> stoppedBeans = new CopyOnWriteArrayList<>();
|
||||||
TestSmartLifecycleBean bean1 = TestSmartLifecycleBean.forShutdownTests(1, 200, stoppedBeans);
|
TestSmartLifecycleBean bean1 = TestSmartLifecycleBean.forShutdownTests(1, 200, stoppedBeans);
|
||||||
TestLifecycleBean simpleBean = TestLifecycleBean.forShutdownTests(stoppedBeans);
|
TestLifecycleBean simpleBean = TestLifecycleBean.forShutdownTests(stoppedBeans);
|
||||||
TestSmartLifecycleBean bean2 = TestSmartLifecycleBean.forShutdownTests(2, 300, stoppedBeans);
|
TestSmartLifecycleBean bean2 = TestSmartLifecycleBean.forShutdownTests(2, 300, stoppedBeans);
|
||||||
TestSmartLifecycleBean bean7 = TestSmartLifecycleBean.forShutdownTests(7, 400, stoppedBeans);
|
TestSmartLifecycleBean bean7 = TestSmartLifecycleBean.forShutdownTests(7, 400, stoppedBeans);
|
||||||
TestSmartLifecycleBean beanMin = TestSmartLifecycleBean.forShutdownTests(Integer.MIN_VALUE, 400, stoppedBeans);
|
TestSmartLifecycleBean beanMin = TestSmartLifecycleBean.forShutdownTests(Integer.MIN_VALUE, 400, stoppedBeans);
|
||||||
StaticApplicationContext context = new StaticApplicationContext();
|
|
||||||
context.getBeanFactory().registerSingleton("beanMin", beanMin);
|
context.getBeanFactory().registerSingleton("beanMin", beanMin);
|
||||||
context.getBeanFactory().registerSingleton("bean1", bean1);
|
context.getBeanFactory().registerSingleton("bean1", bean1);
|
||||||
context.getBeanFactory().registerSingleton("bean2", bean2);
|
context.getBeanFactory().registerSingleton("bean2", bean2);
|
||||||
context.getBeanFactory().registerSingleton("bean7", bean7);
|
context.getBeanFactory().registerSingleton("bean7", bean7);
|
||||||
context.getBeanFactory().registerSingleton("simpleBean", simpleBean);
|
context.getBeanFactory().registerSingleton("simpleBean", simpleBean);
|
||||||
context.getBeanFactory().registerDependentBean("bean2", "simpleBean");
|
context.getBeanFactory().registerDependentBean("bean2", "simpleBean");
|
||||||
|
|
||||||
context.refresh();
|
context.refresh();
|
||||||
assertThat(beanMin.isRunning()).isTrue();
|
assertThat(beanMin.isRunning()).isTrue();
|
||||||
assertThat(bean1.isRunning()).isTrue();
|
assertThat(bean1.isRunning()).isTrue();
|
||||||
@@ -611,6 +653,7 @@ class DefaultLifecycleProcessorTests {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private static class TestLifecycleBean implements Lifecycle {
|
private static class TestLifecycleBean implements Lifecycle {
|
||||||
|
|
||||||
private final CopyOnWriteArrayList<Lifecycle> startedBeans;
|
private final CopyOnWriteArrayList<Lifecycle> startedBeans;
|
||||||
|
|||||||
Reference in New Issue
Block a user