diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/LazyInitializationBeanFactoryPostProcessor.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/LazyInitializationBeanFactoryPostProcessor.java index 85c88cdd13c..9c5990fa75f 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/LazyInitializationBeanFactoryPostProcessor.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/LazyInitializationBeanFactoryPostProcessor.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2022 the original author or authors. + * Copyright 2012-2024 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. @@ -37,11 +37,15 @@ import org.springframework.core.Ordered; * automatically excluded from lazy initialization to ensure that their * {@link SmartInitializingSingleton#afterSingletonsInstantiated() callback method} is * invoked. + *

+ * Beans that are in the {@link BeanDefinition#ROLE_INFRASTRUCTURE infrastructure role} + * are automatically excluded from lazy initialization, too. * * @author Andy Wilkinson * @author Madhura Bhave * @author Tyler Van Gorder * @author Phillip Webb + * @author Moritz Halbritter * @since 2.2.0 * @see LazyInitializationExcludeFilter */ @@ -63,6 +67,7 @@ public final class LazyInitializationBeanFactoryPostProcessor implements BeanFac ArrayList filters = new ArrayList<>( beanFactory.getBeansOfType(LazyInitializationExcludeFilter.class, false, false).values()); filters.add(LazyInitializationExcludeFilter.forBeanTypes(SmartInitializingSingleton.class)); + filters.add(new InfrastructureRoleLazyInitializationExcludeFilter()); return filters; } @@ -105,4 +110,18 @@ public final class LazyInitializationBeanFactoryPostProcessor implements BeanFac return Ordered.HIGHEST_PRECEDENCE; } + /** + * Excludes all {@link BeanDefinition bean definitions} which have the infrastructure + * role from lazy initialization. + */ + private static final class InfrastructureRoleLazyInitializationExcludeFilter + implements LazyInitializationExcludeFilter { + + @Override + public boolean isExcluded(String beanName, BeanDefinition beanDefinition, Class beanType) { + return beanDefinition.getRole() == BeanDefinition.ROLE_INFRASTRUCTURE; + } + + } + } diff --git a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/LazyInitializationBeanFactoryPostProcessorTests.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/LazyInitializationBeanFactoryPostProcessorTests.java index e42544fb6bd..e8cf24f20d6 100644 --- a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/LazyInitializationBeanFactoryPostProcessorTests.java +++ b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/LazyInitializationBeanFactoryPostProcessorTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2021 the original author or authors. + * Copyright 2012-2024 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. @@ -22,6 +22,7 @@ import java.util.List; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.SmartInitializingSingleton; +import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import static org.assertj.core.api.Assertions.assertThat; @@ -30,6 +31,7 @@ import static org.assertj.core.api.Assertions.assertThat; * Tests for {@link LazyInitializationBeanFactoryPostProcessor}. * * @author Andy Wilkinson + * @author Moritz Halbritter */ class LazyInitializationBeanFactoryPostProcessorTests { @@ -58,6 +60,19 @@ class LazyInitializationBeanFactoryPostProcessorTests { } } + @Test + void whenLazyInitializationIsEnabledThenInfrastructureRoleBeansAreInitializedDuringRefresh() { + try (AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext()) { + context.addBeanFactoryPostProcessor(new LazyInitializationBeanFactoryPostProcessor()); + context.register(BeanState.class); + context.registerBean(ExampleBean.class, + (definition) -> definition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE)); + context.refresh(); + BeanState beanState = context.getBean(BeanState.class); + assertThat(beanState.initializedBeans).containsExactly(ExampleBean.class); + } + } + static class ExampleBean { ExampleBean(BeanState beanState) {