Spring Boot 2.2 中的延迟加载

1. 前言

随着咱们项目的不断迭代 Bean 的数量会大大增长,若是都在启动时进行初始化会很是耗时。Spring Boot 容许延迟初始化应用程序, 也就是根据须要初始化 Spring Bean,而不是在 Spring Boot 启动时建立全部的 Bean。这样的就能够减小应用程序启动花费的时间。延迟初始化一般又被称为“懒加载”。java

2. 延迟初始化

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

注意:如下特性在 Spring Boot 2.2.x 中存在

2.1 全局初始化

全局初始化咱们能够经过编程的方式来实现,须要咱们来改变 Spring Boot Main方法的写法。编程

一般咱们的 Main 方法是这样的,注意这里还没声明全局懒加载app

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

全局懒加载写法一:测试

/**
 * @author felord.cn
 * @since 2020/3/31 22:53
 */
@SpringBootApplication
public class DemoSpringbootApplication {
    @Lazy
    public static void main(String[] args) {
        SpringApplication sa = new SpringApplication(DemoSpringbootApplication.class);

        sa.setLazyInitialization(true);
        sa.run(args);
    }
}

全局懒加载写法二:ui

/**
 * @author felord.cn
 * @since 2020/3/31 22:53
 */
@SpringBootApplication
public class DemoSpringbootApplication {
    @Lazy
    public static void main(String[] args) {
       SpringApplicationBuilder sab = new SpringApplicationBuilder(DemoSpringbootApplication.class);
        
        sab.lazyInitialization(true).run(args);
    }
}

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

咱们还能够采起更简单的配置文件(application.properties)的方式来配置延迟初始化:spa

# 默认是关闭的 false
spring.main.lazy-initialization=true

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

控制器blog

/**
 * @author felord.cn
 * @since 2020/3/31 23:31
 */
@RestController
@RequestMapping
public class FooController {
    private FooService fooService;
    
    public FooController(FooService fooService) {
        System.out.println("fooController init...")
        this.fooService = fooService;
    }

    @GetMapping("/req")
    public Map<String, String> demo() {
        System.out.println("Preparing HTTP request...");
        return fooService.response();
    }

}

服务层

/**
 * @author felord.cn
 * @since 2020/3/31 23:36
 */
@Service
public class FooService {
    public FooService() {
        System.out.println("fooService init ...");
    }

    public Map<String, String> response() {
        Map<String, String> map = new HashMap<>();
        map.put("msg","from fooService");
        return map;
    }
}

调用 /req 接口后咱们发现,不仅仅 FooControllerFooService 在第一次调用初始化,连 Spring MVC 核心 DispatcherServlet 都是第一次调用时初始化。

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 方法的几种姿式也进行了展现,但愿对你的实际开发有所帮助。关注公众号:Felordcn 将自动获取技术干货资料。

相关文章
相关标签/搜索