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");
* 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.
* <p>
* 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<LazyInitializationExcludeFilter> 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;
}
}
}

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");
* 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) {