diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jackson/JacksonAutoConfiguration.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jackson/JacksonAutoConfiguration.java index 99f0f7e1df..895ba78b87 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jackson/JacksonAutoConfiguration.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jackson/JacksonAutoConfiguration.java @@ -38,8 +38,7 @@ import com.fasterxml.jackson.databind.cfg.ConstructorDetector; import com.fasterxml.jackson.module.paramnames.ParameterNamesModule; import org.springframework.beans.BeanUtils; -import org.springframework.beans.factory.BeanFactoryUtils; -import org.springframework.beans.factory.ListableBeanFactory; +import org.springframework.beans.factory.ObjectProvider; import org.springframework.boot.autoconfigure.AutoConfiguration; import org.springframework.boot.autoconfigure.AutoConfigurationPackages; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; @@ -171,21 +170,21 @@ public class JacksonAutoConfiguration { @Bean StandardJackson2ObjectMapperBuilderCustomizer standardJacksonObjectMapperBuilderCustomizer( - ApplicationContext applicationContext, JacksonProperties jacksonProperties) { - return new StandardJackson2ObjectMapperBuilderCustomizer(applicationContext, jacksonProperties); + JacksonProperties jacksonProperties, ObjectProvider modules) { + return new StandardJackson2ObjectMapperBuilderCustomizer(jacksonProperties, modules.stream().toList()); } static final class StandardJackson2ObjectMapperBuilderCustomizer implements Jackson2ObjectMapperBuilderCustomizer, Ordered { - private final ApplicationContext applicationContext; - private final JacksonProperties jacksonProperties; - StandardJackson2ObjectMapperBuilderCustomizer(ApplicationContext applicationContext, - JacksonProperties jacksonProperties) { - this.applicationContext = applicationContext; + private final Collection modules; + + StandardJackson2ObjectMapperBuilderCustomizer(JacksonProperties jacksonProperties, + Collection modules) { this.jacksonProperties = jacksonProperties; + this.modules = modules; } @Override @@ -305,8 +304,7 @@ public class JacksonAutoConfiguration { } private void configureModules(Jackson2ObjectMapperBuilder builder) { - Collection moduleBeans = getBeans(this.applicationContext, Module.class); - builder.modulesToInstall(moduleBeans.toArray(new Module[0])); + builder.modulesToInstall(this.modules.toArray(new Module[0])); } private void configureLocale(Jackson2ObjectMapperBuilder builder) { @@ -340,10 +338,6 @@ public class JacksonAutoConfiguration { } } - private static Collection getBeans(ListableBeanFactory beanFactory, Class type) { - return BeanFactoryUtils.beansOfTypeIncludingAncestors(beanFactory, type).values(); - } - } } diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/jackson/JacksonAutoConfigurationTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/jackson/JacksonAutoConfigurationTests.java index 75831041be..0f2d292790 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/jackson/JacksonAutoConfigurationTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/jackson/JacksonAutoConfigurationTests.java @@ -50,6 +50,7 @@ import com.fasterxml.jackson.module.paramnames.ParameterNamesModule; import org.assertj.core.api.InstanceOfAssertFactories; import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.BeanCurrentlyInCreationException; import org.springframework.boot.autoconfigure.AutoConfigurationPackage; import org.springframework.boot.autoconfigure.AutoConfigurations; import org.springframework.boot.autoconfigure.http.HttpMessageConvertersAutoConfiguration; @@ -447,6 +448,14 @@ class JacksonAutoConfigurationTests { }); } + @Test + void jsonComponentThatInjectsObjectMapperCausesBeanCurrentlyInCreationException() { + this.contextRunner.withUserConfiguration(CircularDependencySerializerConfiguration.class).run((context) -> { + assertThat(context).hasFailed(); + assertThat(context).getFailure().hasRootCauseInstanceOf(BeanCurrentlyInCreationException.class); + }); + } + private void assertParameterNamesModuleCreatorBinding(Mode expectedMode, Class... configClasses) { this.contextRunner.withUserConfiguration(configClasses).run((context) -> { DeserializationConfig deserializationConfig = context.getBean(ObjectMapper.class) @@ -657,4 +666,24 @@ class JacksonAutoConfigurationTests { } + @JsonComponent + static class CircularDependencySerializer extends JsonSerializer { + + CircularDependencySerializer(ObjectMapper objectMapper) { + + } + + @Override + public void serialize(String value, JsonGenerator gen, SerializerProvider serializers) throws IOException { + + } + + } + + @Import(CircularDependencySerializer.class) + @Configuration(proxyBeanMethods = false) + static class CircularDependencySerializerConfiguration { + + } + }