Exclude infrastructure beans from lazy initialization

Closes gh-39831
This commit is contained in:
Moritz Halbritter 2024-03-28 09:05:27 +01:00
parent e4462b0940
commit 9c68ce5900
2 changed files with 36 additions and 2 deletions

View File

@ -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"); * 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.
@ -37,11 +37,15 @@ import org.springframework.core.Ordered;
* automatically excluded from lazy initialization to ensure that their * automatically excluded from lazy initialization to ensure that their
* {@link SmartInitializingSingleton#afterSingletonsInstantiated() callback method} is * {@link SmartInitializingSingleton#afterSingletonsInstantiated() callback method} is
* invoked. * invoked.
* <p>
* Beans that are in the {@link BeanDefinition#ROLE_INFRASTRUCTURE infrastructure role}
* are automatically excluded from lazy initialization, too.
* *
* @author Andy Wilkinson * @author Andy Wilkinson
* @author Madhura Bhave * @author Madhura Bhave
* @author Tyler Van Gorder * @author Tyler Van Gorder
* @author Phillip Webb * @author Phillip Webb
* @author Moritz Halbritter
* @since 2.2.0 * @since 2.2.0
* @see LazyInitializationExcludeFilter * @see LazyInitializationExcludeFilter
*/ */
@ -63,6 +67,7 @@ public final class LazyInitializationBeanFactoryPostProcessor implements BeanFac
ArrayList<LazyInitializationExcludeFilter> filters = new ArrayList<>( ArrayList<LazyInitializationExcludeFilter> filters = new ArrayList<>(
beanFactory.getBeansOfType(LazyInitializationExcludeFilter.class, false, false).values()); beanFactory.getBeansOfType(LazyInitializationExcludeFilter.class, false, false).values());
filters.add(LazyInitializationExcludeFilter.forBeanTypes(SmartInitializingSingleton.class)); filters.add(LazyInitializationExcludeFilter.forBeanTypes(SmartInitializingSingleton.class));
filters.add(new InfrastructureRoleLazyInitializationExcludeFilter());
return filters; return filters;
} }
@ -105,4 +110,18 @@ public final class LazyInitializationBeanFactoryPostProcessor implements BeanFac
return Ordered.HIGHEST_PRECEDENCE; 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;
}
}
} }

View File

@ -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"); * 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.
@ -22,6 +22,7 @@ import java.util.List;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.SmartInitializingSingleton; import org.springframework.beans.factory.SmartInitializingSingleton;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
@ -30,6 +31,7 @@ import static org.assertj.core.api.Assertions.assertThat;
* Tests for {@link LazyInitializationBeanFactoryPostProcessor}. * Tests for {@link LazyInitializationBeanFactoryPostProcessor}.
* *
* @author Andy Wilkinson * @author Andy Wilkinson
* @author Moritz Halbritter
*/ */
class LazyInitializationBeanFactoryPostProcessorTests { 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 { static class ExampleBean {
ExampleBean(BeanState beanState) { ExampleBean(BeanState beanState) {