如何Lazy加载所有Springbean,无论它是由Springboot2.2中的@Bean还是@Component定义



我正在编写一个spring应用程序,它是交互式的,基本上可以处理许多命令,如创建、列出、更新、删除各种类型的资源。

现在,假设应用程序的一次运行只处理一个命令,程序就会退出。

对于要验证命令的所有类,执行该命令,每个资源所需的工厂类都有一个单独的类,每个类都用spring的@Component注释进行注释,以管理所有组件。

还有一些通过@Bean方法手动定义的bean。

现在,我的应用程序首先确定了要执行的命令类型(创建、删除、列出、更新等(,我希望创建该命令的唯一bean,并根据需要自动连接(从用户那里获取命令后(,我想避免创建与其他命令相关的数十个bean。

在搜索过程中,我了解了spring提供的Beans的懒惰实例化。然而,我不确定这是否是我正在寻找的武器。

我尝试了什么

  • 首先我发现了@Lazy注释,但由于我想懒惰地加载所有的Beans,我不想在每个类中到处写@Lazy
  • 然后我在application.yml中找到了下面的属性设置
spring:
main:
lazy-initialization: true

我试过了,但仍然没有懒散地创造豆子。

我的应用程序.yml文件看起来像这个

spring:
main:
lazy-initialization: true

我的SpringBootApplication主文件如下所示:

@Slf4j
@SpringBootApplication
public class SpringBootApplication {
public static void main(String[] args) {
System.out.println("Loading Application...");
ApplicationContext context = SpringApplication.run(SpringBootApplication.class, args);

final AtomicInteger counter = new AtomicInteger(0);
log.info("**************** START: Total Bean Objects: {} ******************", context.getBeanDefinitionCount());
Arrays.asList(context.getBeanDefinitionNames())
.forEach(beanName -> {
log.info("{}) Bean Name: {} ", counter.incrementAndGet(), beanName);
});
log.info("**************** END: Total Bean: {} ******************", context.getBeanDefinitionCount());
}
}

我的其他类如下:


@Component
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class MyClass1 implements ResourceCreator<MyClass2, MyClass3> {
private final RequestValidatorImpl requestValidator;
private final ResourceCreator resourceCreator;
@Override
public MyClass2 toImplementFunction(MyClass3 myclass3) {
//logic
}

在运行应用程序时,它会打印我注释@Component的所有类以及@Bean方法创建的Bean。

我也尝试过在Application.properties中使用以下内容,但仍然没有用。

spring.main.lazy-initialization=true

此外,如果你愿意,请评论我是否应该像现在使用的那样为每个类使用@Component,以及什么是更好的做法。

我认为您误解了所传递的lazy标志的含义,这意味着只有在调用对象时才会创建该对象,但它并没有表示不会扫描该包。Spring将扫描所有包并存储bean定义名称,但只有当调用它时,如果您已经将lazy标志传递给它,它才会创建对象

您可以通过检查在传递lazy标志时创建的bean数量为true和false来验证这种行为。你可以按照下面的进行检查

ApplicationContext context = SpringApplication.run(SpringBootApplication.class, args);
System.out.println("count:"+context.getBeanDefinitionCount());

编辑于2020年4月7日开始

另一种方法是创建一个构造函数,并使用它来注入自动连接的属性,并在它们进入构造函数时打印出日志。

我在一个示例项目中也做了同样的事情,下面是他的结果,第一个是急于初始化,第二个是懒惰。

spring.main.lazy-initialization=false应用程序日志

Inside Constructor
calling bean
inside bean method

spring.main.lazy-initialization=true应用程序日志

calling bean
Inside Constructor
inside bean method

编辑于2020年4月7日结束

如果我回答了你的问题,请将此标记为已回答。谢谢

长话短说:对于任何想要延迟初始化整个Spring Boot上下文的人来说,将此属性设置为true是可行的:

spring.main.lazy-initialization=true

Pro提示:它可以与@Lazy注释组合使用,设置为false;因此,除了我们用@lazy(false(显式配置的bean之外,所有定义的bean都将使用惰性初始化。

通过这种方式,延迟初始化将变为opt-out,而不是默认的opt-In

最新更新