当前位置: 首页 > 知识库问答 >
问题:

如何延迟加载所有SpringBean,无论它是由Springboot 2.2中的@Bean还是@Component定义的

苏华荣
2023-03-14

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

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

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

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

现在,我的应用程序首先确定了执行哪种命令(创建、删除、列表、更新等),我希望在需要时(从用户获取命令后)创建并自动连接该命令的唯一bean,并且我希望避免创建几十个与其他命令相关的bean。

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

我试过的

  • 首先我发现@Lazy annotation,但因为我想懒洋洋地加载所有bean,所以我不想在每个类中到处写@Lazy
spring:
  main:
    lazy-initialization: true

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

我的申请。yml文件是这样的

spring:
  main:
    lazy-initialization: true

我的主要SpringBoot应用程序文件如下所示:

@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的所有类以及@Beanhtml" target="_blank">方法创建的Bean。

我还尝试在应用程序中使用下面的代码。属性,但仍然没有用。

spring.main.lazy-initialization=true

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

共有2个答案

松增
2023-03-14

长话短说:对于任何想要懒洋洋地初始化整个Spring Boot上下文的人来说,将这个属性设置为true是一个好办法:

spring.main.lazy-initialization=true

专业提示:它可以与@Lazy注释结合使用,设置为false;所以所有定义的bean都将使用懒惰初始化,除了我们显式配置的@Lazy(false)。

这样,延迟初始化就变成了opt-out,而不是默认的opt-In。

强承望
2023-03-14

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

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

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

2020年4月7日开始编辑

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

我在一个示例项目中也做了同样的工作,下面是结果,第一个是针对急切的初始化,第二个是针对懒惰的初始化。

spring。主要的延迟初始化=false应用程序日志

Inside Constructor
calling bean
inside bean method

spring。主要的lazy initialization=true应用程序日志

calling bean
Inside Constructor
inside bean method

2020年4月7日编辑结束

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

 类似资料:
  • 问题内容: 我正在使用基于Java的配置来设置我的Spring应用程序上下文,如下所示: 像您期望的那样,在配置中显式定义的Bean会延迟加载。但是,带有注释的扫描类始终会急切加载。我该如何解决? 任何帮助表示赞赏。 请注意,对于包中的类,我也可以通过对其进行注释来解决。但是另一个项目没有对Spring的依赖,我想一直保持这种状态(因此,不是)。 还要注意,这在基于XML的配置中不会成为问题。目前

  • 1、mybatis 是否支持延迟加载? 延迟加载其实就是讲数据加载时机推迟,比如推迟嵌套查询的时机。 延迟加载可以实现先查询主表,按需实时做关联查询,返回关联表结果集,一定程度上提高了效率。 mybatis仅支持关联对象association和关联集合对象collection的延迟加载,association是一对一,collection是一对多查询,在mybatis配置文件中可以配置lazylo

  • 在骆驼路线中是否有任何方法可以懒惰地装载豆子?

  • 问题内容: 什么是Java的延迟加载?我不明白这个过程。有人可以帮助我了解延迟加载的过程吗? 问题答案: 假设您有一个父母,而那个父母有很多孩子。Hibernate现在可以“延迟加载”子级,这意味着它在加载父级时实际上并不会加载所有子级。而是在要求时加载它们。您可以显式地请求此请求,或者,更常见的是,当您尝试访问孩子时,hibernate会自动加载它们。 延迟加载可以帮助显着提高性能,因为通常您不

  • 问题内容: Java中的延迟加载是什么?我不明白这个过程。有人可以帮助我了解延迟加载的过程吗? 问题答案: 假设你有一个父母,而那个父母有很多孩子。Hibernate现在可以“延迟加载”子级,这意味着在加载父级时,它实际上并未加载所有子级。而是在要求时加载它们。你可以显式地请求此请求,也可以是更常见的情况,当你尝试访问孩子时,hibernate会自动加载它们。 延迟加载可以帮助显着提高性能,因为通

  • 问题内容: 我在实体中有一个懒惰的访存类型集合。我正在使用Spring Data(JpaRepository)来访问实体。 我想要服务类和当前实现中的两个功能如下: 获取父级时,“子级”应为null } 提取父项时,应填写“子项”: } 从RestController返回“父”实体时,将引发以下异常: org.springframework.http.converter.HttpMessageNo