启动未初始化小应用程序_SpringBoot详细打印启动时异常堆栈信息

a8479942e425bd52f5971b3874cf5643.png

1. 前言

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

2. 延迟初始化

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

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

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) {        System.out.println("fooController init...")        this.fooService = fooService;    }    @GetMapping("/req")    public Map demo() {        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 Map response() {        Map map = new HashMap<>();        map.put("msg","from fooService");        return map;    }}复制代码

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

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在Spring Boot中,您可以使用@Configuration注释来标记一个类,使其成为配置类,从而配置您的应用程序。要根据请求头中的appid来初始化您的应用程序,请按以下步骤操作: 1. 创建一个@Configuration类并在其中定义一个@Bean方法,该方法将返回一个类型为HandlerInterceptor的对象。 2. 在@Bean方法中实例化并返回您的HandlerInterceptor对象。在HandlerInterceptor对象的preHandle方法中,您可以检查请求头中的appid并根据需要执行初始化操作。 3. 使用@EnableWebMvc注释启用Spring MVC并注册您的HandlerInterceptor对象。这可以通过在@Configuration类上添加@EnableWebMvc注释来完成。 下面是一个示例代码,演示了如何使用@Configuration和@Bean来创建HandlerInterceptor对象并将其注册到Spring MVC中: ``` @Configuration @EnableWebMvc public class AppConfig implements WebMvcConfigurer { @Bean public HandlerInterceptor myInterceptor() { return new MyInterceptor(); } @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(myInterceptor()); } } public class MyInterceptor implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { String appid = request.getHeader("appid"); // 根据请求头中的appid执行初始化操作 return true; } } ``` 在这个例子中,我们创建了一个名为MyInterceptor的HandlerInterceptor对象,该对象检查请求头中的appid并根据需要执行初始化操作。我们使用@Configuration和@Bean来创建这个HandlerInterceptor对象,并使用@EnableWebMvc来启用Spring MVC并注册这个对象。最后,在addInterceptors方法中,我们将HandlerInterceptor对象添加到InterceptorRegistry中,以便它可以拦截所有的请求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值