GH-377 - Avoid initialization of ApplicationModulesRuntime if possible.
This commit is contained in:
@@ -15,15 +15,13 @@
|
||||
*/
|
||||
package org.springframework.modulith.runtime.autoconfigure;
|
||||
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.aop.support.AopUtils;
|
||||
import org.springframework.beans.factory.ListableBeanFactory;
|
||||
import org.springframework.beans.factory.ObjectProvider;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.boot.autoconfigure.AutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingClass;
|
||||
import org.springframework.boot.context.event.ApplicationStartedEvent;
|
||||
@@ -40,6 +38,7 @@ import org.springframework.modulith.core.FormatableType;
|
||||
import org.springframework.modulith.runtime.ApplicationModulesRuntime;
|
||||
import org.springframework.modulith.runtime.ApplicationRuntime;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.function.ThrowingSupplier;
|
||||
|
||||
/**
|
||||
* Auto-configuration to register a {@link SpringBootApplicationRuntime}, a {@link ApplicationModulesRuntime} and an
|
||||
@@ -65,23 +64,25 @@ class SpringModulithRuntimeAutoConfiguration {
|
||||
@ConditionalOnMissingBean
|
||||
static ApplicationModulesRuntime modulesRuntime(ApplicationRuntime runtime) {
|
||||
|
||||
var mainClass = runtime.getMainApplicationClass();
|
||||
var modules = EXECUTOR
|
||||
.submit(() -> ApplicationModulesBootstrap.initializeApplicationModules(mainClass));
|
||||
ThrowingSupplier<ApplicationModules> modules = () -> EXECUTOR
|
||||
.submit(() -> ApplicationModulesBootstrap.initializeApplicationModules(runtime.getMainApplicationClass()))
|
||||
.get();
|
||||
|
||||
return new ApplicationModulesRuntime(toSupplier(modules), runtime);
|
||||
return new ApplicationModulesRuntime(modules, runtime);
|
||||
}
|
||||
|
||||
@Bean
|
||||
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
|
||||
@ConditionalOnBean(ApplicationModuleInitializer.class)
|
||||
static ApplicationListener<ApplicationStartedEvent> applicationModuleInitializingListener(
|
||||
ListableBeanFactory beanFactory) {
|
||||
ObjectProvider<ApplicationModulesRuntime> runtime,
|
||||
ObjectProvider<ApplicationModuleInitializer> initializers) {
|
||||
|
||||
return event -> {
|
||||
|
||||
var modules = beanFactory.getBean(ApplicationModulesRuntime.class).get();
|
||||
var modules = runtime.getObject().get();
|
||||
|
||||
beanFactory.getBeanProvider(ApplicationModuleInitializer.class).stream() //
|
||||
initializers.stream() //
|
||||
.sorted(modules.getComparator()) //
|
||||
.map(it -> LOGGER.isDebugEnabled() ? new LoggingApplicationModuleInitializerAdapter(it, modules) : it)
|
||||
.forEach(ApplicationModuleInitializer::initialize);
|
||||
@@ -160,17 +161,6 @@ class SpringModulithRuntimeAutoConfiguration {
|
||||
}
|
||||
}
|
||||
|
||||
private static Supplier<ApplicationModules> toSupplier(Future<ApplicationModules> modules) {
|
||||
|
||||
return () -> {
|
||||
try {
|
||||
return modules.get();
|
||||
} catch (Exception o_O) {
|
||||
throw new RuntimeException(o_O);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Auto-configuration to react to ArchUnit missing on the runtime classpath.
|
||||
*
|
||||
|
||||
@@ -23,6 +23,7 @@ import org.springframework.boot.autoconfigure.AutoConfigurations;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.boot.test.context.FilteredClassLoader;
|
||||
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
|
||||
import org.springframework.modulith.ApplicationModuleInitializer;
|
||||
import org.springframework.modulith.runtime.ApplicationModulesRuntime;
|
||||
import org.springframework.modulith.runtime.ApplicationRuntime;
|
||||
|
||||
@@ -46,11 +47,8 @@ class SpringModulithRuntimeAutoConfigurationIntegrationTests {
|
||||
.withUserConfiguration(SampleApp.class)
|
||||
.withConfiguration(AutoConfigurations.of(SpringModulithRuntimeAutoConfiguration.class))
|
||||
.run(context -> {
|
||||
|
||||
assertThat(context.getBean(ApplicationRuntime.class)).isNotNull();
|
||||
assertThat(context.getBean(ApplicationModulesRuntime.class)).isNotNull();
|
||||
|
||||
context.close();
|
||||
});
|
||||
}
|
||||
|
||||
@@ -62,13 +60,25 @@ class SpringModulithRuntimeAutoConfigurationIntegrationTests {
|
||||
.withConfiguration(AutoConfigurations.of(SpringModulithRuntimeAutoConfiguration.class))
|
||||
.withClassLoader(new FilteredClassLoader(ClassFileImporter.class))
|
||||
.run(context -> {
|
||||
|
||||
assertThat(context).hasFailed();
|
||||
assertThat(context.getStartupFailure().getCause())
|
||||
.isInstanceOf(BeanInstantiationException.class)
|
||||
.cause().isInstanceOf(MissingRuntimeDependency.class);
|
||||
|
||||
context.close();
|
||||
});
|
||||
}
|
||||
|
||||
@Test // GH-375, GH-377
|
||||
void registersInitializingListenerIfInitializersPresent() {
|
||||
|
||||
var beanName = "applicationModuleInitializingListener";
|
||||
var runner = new ApplicationContextRunner()
|
||||
.withConfiguration(AutoConfigurations.of(SpringModulithRuntimeAutoConfiguration.class));
|
||||
|
||||
// No initializer -> no listener
|
||||
runner.run(context -> assertThat(context).doesNotHaveBean(beanName));
|
||||
|
||||
// Initializer -> listener
|
||||
runner.withBean(ApplicationModuleInitializer.class, () -> () -> {})
|
||||
.run(context -> assertThat(context).hasBean(beanName));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user