SpringBoot项目速度提升之延迟初始化(Lazy Initialization)详解
作者:不一样的科技宅 发布时间:2021-11-27 06:37:22
前言
在一个名为种花家的小镇上,生活着一群热爱编程的人。他们致力于构建出高效、可维护的软件系统,而 Spring Boot 框架成为了他们的不二之选。这个小镇上的人们每天都在用 Spring Boot 框架创造着令人瞩目的应用程序。
然而,随着时间的推移,他们的应用程序变得越来越庞大,包含了许多不同的模块和组件。在应用程序启动的时候,所有的 bean 都会被一次性初始化,这导致了一个令人头疼的问题:启动时间变得越来越长了。
小镇的居民们开始感到困扰。他们意识到,无论是在开发环境还是在生产环境中,启动时间的长短都直接关系到他们的工作效率和用户体验。于是,他们寻找一种解决方案,希望能够在保证应用程序正常运行的同时,减少启动时间的开销。
正当大家纠结不已时,一个编程少侠出现了。他名叫不一样的科技宅,他告诉大家,有一种叫做"延迟初始化"的策略,可以帮助他们解决这个问题。
据说,延迟初始化能够将 bean 的初始化推迟到第一次使用时进行,而不是在应用程序启动时立即初始化。这样一来,只有当某个 bean 真正被需要时,才会进行初始化,避免了不必要的资源消耗和时间开销。
是什么?
延迟初始化(Lazy Initialization)是一种在需要时才创建或加载对象的策略,以减少启动时间和资源消耗。在 Spring 中,延迟初始化允许将 Bean 的创建推迟到第一次访问该 Bean 时才进行,而不是在应用程序启动时立即创建。
有啥用?
节省资源
当应用程序中存在大量的 bean 时,立即初始化所有 bean 可能会占用大量的内存和处理时间。通过延迟初始化,只有在需要使用 bean 时才会进行初始化,可以避免不必要的资源消耗。
加快启动时间
延迟初始化可以减少应用程序启动时间,因为只有在需要时才会加载和初始化 bean。对于那些在应用程序启动时可能不会使用的较大或复杂的 bean,延迟初始化可以显著加快启动时间。
解决循环依赖
Spring 容器可以管理 bean 之间的依赖关系。当存在循环依赖时,延迟初始化可以帮助解决这个问题。通过延迟初始化,Spring 容器可以在运行时逐个解析和满足 bean 之间的依赖,而不是在初始化阶段发现无法解决的循环依赖。
如何实现?
Spring Boot 中实现延迟初始化 Bean,可以采取以下四种方法:
1.对于使用注解配置的 Bean,可以在 Bean 的定义上使用 @Lazy
注解来实现延迟初始化。
示例:
@Lazy
@Component
public class MyBean {
// Bean 的定义
}
2.对于使用 Java 配置类的方式,可以在 @Bean
注解上使用 @Lazy
注解,以实现延迟初始化。
示例:
@Configuration
public class AppConfig {
@Lazy
@Bean
public MyBean myBean() {
// Bean 的定义
return new MyBean();
}
}
3.对于 XML 配置的 Bean,可以在 <bean>
元素上设置 lazy-init
属性为 true
,以实现延迟初始化。
示例:
<bean id="myBean" class="com.example.MyBean" lazy-init="true" />
4.对于使用@ComponentScan
注解,可以配置属性lazyInit = true
实现某些包下面所有的 bean 延迟初始化。
示例:
package com.example.demo.bean;
import org.springframework.stereotype.Component;
@Component
public class MyBean {
public MyBean() {
System.out.println("My bean init success.");
}
}
@SpringBootApplication
@ComponentScan(value = "com.example.demo.bean", lazyInit = true)
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
全局懒加载
上面演示案例,意味着我们只能对自己实现的 bean 进配置。但是项目中肯定会引入很多第三方的 starter,比如 redis,mq。如果想对引入的第三方库进行配置,那就不太容易了,所以我们可以开启全局懒加载。
配置文件增加下面的配置:
spring:
main:
lazy-initialization: true #默认false 关闭
开启了全局懒加载,想要过滤某个 bean,可以通过设置 @Lazy(false) 排除。
@Component
@Lazy(false)
public class MyBean {
public MyBean() {
System.out.println("My bean init success.");
}
}
还有一种是通过配置 LazyInitializationExcludeFilter 规则实现排除。
@Configuration
public class AppConfig {
@Bean
LazyInitializationExcludeFilter integrationLazyInitExcludeFilter() {
return LazyInitializationExcludeFilter.forBeanTypes(MyBean.class);
}
}
注意的点
@Lazy 注解的使用
要确保在正确的位置使用@Lazy 注解。通常情况下,将其添加在 Bean 的定义上,例如@Component、@Service、@Repository 等注解上。这样可以确保被标记的 Bean 在第一次使用时才会进行初始化。
依赖关系的处理
懒加载的 Bean 可能会被其他 Bean 所依赖。在处理依赖关系时,要确保依赖的 Bean 已经被初始化或者也进行了懒加载。否则,可能会导致依赖注入失败或出现异常。
延迟初始化带来的影响
懒加载虽然可以提高应用的启动性能,但也会带来一些影响。由于 Bean 的初始化被延迟到第一次使用,因此在初始化时可能会出现较长的延迟,对于需要立即使用的 Bean 可能会造成一定的等待时间。
内存消耗的控制
懒加载虽然可以减少应用启动时的内存消耗,但也需要注意对内存的控制。如果应用中存在大量的懒加载 Bean,并且这些 Bean 在实际使用中并不频繁,可能会导致过多的内存占用。因此,需要根据应用的具体情况,合理使用懒加载,避免过度消耗内存。
运行时异常的处理
由于懒加载将 Bean 的初始化延迟到运行时,因此在初始化过程中可能会发生异常。要确保适当地处理这些异常,以防止应用的崩溃或不可预料的行为。
来源:https://juejin.cn/post/7231517390185988157


猜你喜欢
- 在Activity之间传递数据还可以利用一些技巧,不管windows还是Linux操作系统,都会支持一种叫剪切板的技术,也就是某一个程序将一
- springboot 启动排除某些bean的注入问题:最近做项目的时候,需要引入其他的jar。然后还需要扫描这些jar里的某些bean。于是
- 本文以实例形式讲述了C语言实现二叉树的非递归遍历方法。是数据结构与算法设计中常用的技巧。分享给大家供大家参考。具体方法如下:先序遍历:voi
- 翻译自 John Demetriou 2019年2月17日 的文章 《C# 8 – Introducing Index Struct And
- 前言大家都知道MySQL数据库很好用,但数据量到了千万以上了,想增加字段是非常痛苦的,这个在MongoDB里就不存在,字段想怎么加就怎么加,
- JOL简介JOL的全称是Java Object Layout。是一个用来分析JVM中Object布局的小工具。包括Object在内存中的占用
- 1.继承Thread类,重写run方法2.实现Runnable接口,重写run方法,实现Runnable接口的实现类的实例对象作为Threa
- 前言事务对java开发的同学来说并不陌生,我们使用事务的目的在于避免产生重复数据或者说利用数据存储中间件的事务特性确保数据的精准性,比如大家
- spring cloud oauth2 feign 遇到的坑关于oauth2相关的内容这里不重复描述,在spring cloud中在管理内部
- Java深入到一定程度,就不可避免的碰到设计模式(design pattern)这一概念,了解设计模式,将使自己对java中的接口或抽象类应
- 目录1、通过session中的token验证步骤1:创建自定义注解步骤2:创建自定义 * (@slf4j是lombok的注解)步骤3:将自定
- 一、springboot 自动配置原理先说说我们自己的应用程序中Bean加入容器的办法:package com.ynunicom.dc.di
- 一、项目简述本系统主要实现的功能有: 学生以及老师的注册登录,在线考试,错题查询,学生管理,问题管理,错题管理,错题查询,分数查询,试卷管
- 本文实例讲述了C#实现农历日历的方法。分享给大家供大家参考。具体实现方法如下://天干 private static
- 前言DataGridView是开发Winform的一个列表展示,类似于表格。学会下面的基本特征用法,再辅以经验,基本功能开发没问题。基本的数
- 邮件绑定功能【需求】1、 用户注册时,输入邮箱2、 通过Javamail技术,向用户邮箱发送一封祝贺邮件1、javamail发送邮件1.1、
- SpringMVC注解@RequestMapping在之前的 hello world 示例中,用到了 @RequestMapping 注解,
- 今天在面试时遇到一道算法的题:给定一个字符串,输出每次字符出现的次数;要求按照顺序输出;自己的思路开始是:1.把String转换char数组
- 背景:本人不是Java开发人员,经过四年多的历练,可以说是一枚BI攻城师了吧,最近粗糙的写了一个Portal来集成cognos报表,下面就入
- 说到网络,相信大家都对TCP、UDP和HTTP协议这些都不是很陌生,学习这部分应该先对端口、Ip地址这些基础知识有一定了解,后面我们都是直接