springboot初始化逻辑_合理利用延迟初始化优化 Spring Boot

本文探讨了Spring Boot的延迟初始化机制,如何通过全局和局部配置实现Bean的懒加载,以减少启动时间。同时,文章提醒注意延迟初始化可能导致的错误暴露延迟和内存管理问题,建议对涉及复杂逻辑的非必要Bean使用此特性。
摘要由CSDN通过智能技术生成

点击上方码农沉思录,选择“设为星标”

优质文章,及时送达

1. 前言

随着我们项目的不断迭代 Bean 的数量会大大增加,如果都在启动时进行初始化会非常耗时。Spring Boot 允许延迟初始化应用程序, 也就是根据需要初始化 Spring Bean,而不是在 Spring Boot 启动时创建所有的 Bean。这样的就可以减少应用程序启动花费的时间。延迟初始化通常又被称为“懒加载”。

2. 延迟初始化

Spring Boot 中的延迟初始化可分为全局延迟初始化和局部初始化。

2.1 全局初始化

全局初始化我们可以通过编程的方式来实现,需要我们来改变 Spring Boot Main方法的写法。

通常我们的 Main 方法是这样的,注意这里还没声明全局懒加载:

/** * @author felord.cn * @since 2020/3/31 22:53 */@SpringBootApplicationpublic class DemoSpringbootApplication {    @Lazy    public static void main(String[] args) {        SpringApplication.run(DemoSpringbootApplication.class,args);    }}

全局懒加载写法一:

/** * @author felord.cn * @since 2020/3/31 22:53 */@SpringBootApplicationpublic class DemoSpringbootApplication {    @Lazy    public static void main(String[] args) {        SpringApplication sa = new SpringApplication(DemoSpringbootApplication.class);        sa.setLazyInitialization(true);        sa.run(args);    }}全局懒加载写法二:/** * @author felord.cn * @since 2020/3/31 22:53 */@SpringBootApplicationpublic class DemoSpringbootApplication {    @Lazy    public static void main(String[] args) {       SpringApplicationBuilder sab = new SpringApplicationBuilder(DemoSpringbootApplication.class);        sab.lazyInitialization(true).run(args);    }}

上面的写法一和写法二都是我们通过编程方式定制一些 Spring Boot 特性,大多数都是全局特性。包括本文讲述的 “懒加载”。

我们还可以采取更简单的配置文件(application.properties)的方式来配置延迟初始化:

默认是关闭的 falsespring.main.lazy-initialization=true

当我们开启了全局的延迟加载后,在 Web 应用程序中将导致许多与 Web 相关的 Bean 直到收到第一次 HTTP 请求后才被初始化。

控制器:

/** * @author felord.cn * @since 2020/3/31 23:31 */@RestController@RequestMappingpublic class FooController {    private FooService fooService;    public FooController(FooService fooService) {        this.fooService = fooService;    }    @GetMapping("/req")    public Mapdemo() {        System.out.println("Preparing HTTP request...");        return fooService.response();    }}

服务层

/** * @author felord.cn * @since 2020/3/31 23:36 */@Servicepublic class FooService {    public FooService() {        System.out.println("fooService init ...");    }    public Mapresponse() {        Mapmap = new HashMap<>();        map.put("msg","from fooService");        return map;    }}

调用 /req 接口后我们发现,不单单 FooController 和 FooService 在第一次调用初始化,连 Spring MVC 核心 DispatcherServlet 都是第一次调用时初始化。

f321f8349bff515d35705206a536d847.png

2.2 局部初始化

如果我们不想让全局延迟初始化作用于个别的 Bean 怎么办?我们可以在这个 Bean 上声明注解 @Lazy(value = false) 即可。你可以改写 2.1 的代码自己试一试。这个 @Lazy 作用于局部,并通过布尔值 value 来控制是否延迟初始化。情况是这样的:

当我们声明全局延迟加载时,@Lazy(value = false)标记的 Bean 会被立即加载。

当我们声明全局不延迟加载时,@Lazy 标记的 Bean 会被延迟加载。

请注意:@Lazy 会影响到 @Configuration 下声明的 Bean

3. 注意事项

延迟初始化的缺点是,如果错误配置的 Bean 是延迟初始化的,则在启动期间将不再发生故障,并且只有在初始化 Bean 时错误才会暴露出来,所以一定要经过严格的测试。

同时还必须注意确保 JVM 具有足够的内存来容纳所有应用程序的 Bean,而不仅仅是启动期间初始化的 Bean。因此建议在启用延迟初始化之前先对 JVM 的堆大小进行必要的检测和微调以保证不会溢出。

那些初始化耗时,具有复杂逻辑,而且不是启动的必要选择的 Bean 应当被延迟初始化。

4. 总结

今天对 Spring Boot 如何进行延迟初始化进行了讲解,同时也说明了一些注意事项。间接地也对 Main 方法的几种姿势也进行了展示,希望对你的实际开发有所帮助。

2a5df234b6cbca76f5269c1f439605d9.png

89098602a0ee36badcba4221f18800cc.png

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值