Both ModuleContextCustomizer and ModuleTypeExcludeFilter contribute to the calculation of the context configuration which the Spring Test Context Framework uses to decide whether it's necessary to create new ApplicationContext instances.
Both of them previously used a Supplier<ModuleTestExecution> to calculate equals(…) and hashCode() which -- by definition -- does not result in the same result even when created with identical input. We now rather use the source class instance eventually backing the ModuleTestExecution, as that is the internal cache key in turn.
We now additionally guard the completion query by event and target identifier to also only apply to publications that have not been completed yet. This will allow databases to optimize the query plan to apply simple comparisons (the date being null) over complex comparisons (the event payload) to reduce the intermediate results to process further and thus improve performance.
If named interfaces are declared in nested packages, the name detection might accidentally pick up the names declared in child packages. We now deliberately only inspect the base package.
As we process a type's entire type hierarchy for dependencies we might discover a foreign module's internal dependencies for modules that declare allowed dependencies explicitly. Explicitly declared dependencies so far solely verified the target being explicitly listed, which, for internal dependencies does not make sense. We now immediately start checking the source and target modules to be equivalent, in which case we can skip any further processing.
We now expose a configuration property spring.modulith.detection-strategy that can take either of the two prepared values "direct-sub-packages" (default) or "explicitly-annotated", or a fully qualified class name of the strategy to use.
Removed ApplicationModuleStrategies enum to avoid exposing the enum values as additional implementations. Those are now held as inline lambda expression in the factory methods on ApplicationModuleStrategy. Extracted the lookup of the strategy to use into ApplicationModuleDetectionStrategyLookup for easier testability.
We're now registering a customizers for both the SimpleAsyncTaskExecutor (used for virtual threads) and the ThreadPoolTaskExecutor to register a ContextPropagatingTaskDecorator.
The previous change unfortunately altered the CacheKey type in a way that it does not result in equal instances for the same set of parameters, primarily because SingletonSupplier does not implement equals(…)/hashCode(). We now resort to include the ModulithMetadata source in the equals(…) / hashCode() calculation rather than the ModulithMetadata instance itself. This also avoids annotation processing during CacheKey instance creation.
We now expose ApplicationRuntime.of(ApplicationContext) to create a SpringBootApplicationRuntime as that's needed a lot in integration tests for runtime and observability components.