11

QQA: Spring Bean 如何开启懒加载

 4 years ago
source link: https://lotabout.me/2021/QQA-how-to-lazy-initialize-spring-beans/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client
Table of Contents

有些 Bean 依赖外部环境,如 Repository 通常依赖数据库连接。一些单元测试中用不到它们,因此希望在测试中不初始化这些 Bean。除此之外,在测试中开启懒加载/延迟初始化(lazy-init),由于跳过了不用的 Bean,还能加快测试运行的速度。

Spring 2.2 之后

在 Spring 2.2 之后,最直接的方式是在 test/resources/application.yml 配置文件中加入如下参数:

spring.main.lazy-initialization: true

内部原理是在 SpringApplication 中,如果检测到该参数为真,则会创建一个 BeanFactoryPostProcessor,用于将“所有” BeanDefinition 的 lazyInit 属性置为真。

if (this.lazyInitialization) {
context.addBeanFactoryPostProcessor(new LazyInitializationBeanFactoryPostProcessor());
}

Spring 2.2 之前

参考这篇文章 ,本质上与 Spring 2.2 的方法一样,需要在测试包中自定义 BeanFactoryPostProcessor,用于将“所有” BeanDefinition 的 lazyInit 属性置为真:

@Component
@Profile("!" + TestLazyBeanInitConfiguration.EAGER_BEAN_INIT)
public class TestLazyBeanInitConfiguration implements BeanFactoryPostProcessor {
public static final String EAGER_BEAN_INIT = "eager-bean-init";

@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
Arrays.stream(beanFactory.getBeanDefinitionNames())
.map(beanFactory::getBeanDefinition)
.forEach(beanDefinition -> beanDefinition.setLazyInit(true));
}
}

如果某个测试不需要懒加载,则通过注解 @ActiveProfiles(TestLazyBeanInitConfiguration.EAGER_BEAN_INIT) 关闭。

@ComponentScan(lazyInit = true) 有坑

通常我会在测试包中创建一个 TestApplication 类,并注解为 @SpringBootApplication 来完成 Bean 的自动扫描。尝试过下面的方式:

@SpringBootApplication
@ComponentScan(lazyInit = true)
public class TestApplication {
}

这种方法对于自动创建的 Bean(即标记为 @Component, @Service 等的类)是有效的。但对于 Configuration 类中通过 @Bean 方式创建的 Bean 无效。毕竟 @ComponentScan 本身控制的就是扫描 Bean 的行为。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK