概叙
科普文:Java基础系列之深入理解Java注解、反射与代理机制_java 注解代理-CSDN博客
科普文:SpringBoot核心注解及应用梳理-CSDN博客
科普文:Java基础系列之【@Async注解遇上循环依赖的坑】_async循环依赖-CSDN博客
科普文:Java基础系列之【Spring参数注解@Value 和@ConfigurationProperties 便捷读取配置信息】-CSDN博客
科普文:spring boot中常用的接口、工具栏、注解整理_springboot接口-CSDN博客
前面有对java注解、spring注解做过梳理,这里我们再看看Spring框架中@Lazy注解的原理、核心类、应用场景。
注解 | 核心目的 | 典型场景 | 耦合度 |
---|---|---|---|
@Lazy | 延迟初始化 | 资源密集型对象、启动优化 | 低 |
@Component | 组件注册 | 通用业务逻辑类 | 无 |
@Order | 执行顺序控制 | 集合注入排序、切面优先级 | 中 |
@DependsOn | 初始化顺序强制依赖 | 隐式依赖的 Bean 初始化顺序控制 | 高 |
注解@Lazy
@Lazy原理
通过代理机制或延迟初始化策略,将 Bean 的创建推迟到首次实际使用时,而非容器启动阶段。
@Lazy核心类
LazyInitBeanFactoryPostProcessor
(Spring 内部处理延迟初始化的核心类)。
@Configuration
public class LazyInitBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
for (String beanName : beanFactory.getBeanDefinitionNames()) {
beanFactory.getBeanDefinition(beanName).setLazyInit(true); //全局启动慢加载
}
}
}
LazyInitBeanFactoryPostProcessor 是 Spring 框架中用于实现 Bean 延迟加载(Lazy-Init)的扩展机制,属于 BeanFactoryPostProcessor
接口的实现类。
其主要作用是通过修改 BeanDefinition 的 lazyInit
属性,动态控制 Bean 的初始化时机,从而优化容器启动性能。
-
延迟加载的作用
通过设置lazyInit=true
,Bean 会在首次被请求时初始化,而非容器启动阶段初始化。这减少了启动时的资源消耗,特别适用于大型应用中非核心或低频使用的 Bean。 -
与 BeanFactoryPostProcessor 的关系
- 执行时机:在容器加载所有 BeanDefinition 完成后、Bean 实例化前触发。
- 操作对象:直接修改 BeanDefinition 的属性(如
lazyInit
)或注册新的 BeanDefinition。 - 典型场景:批量配置 Bean 的延迟初始化,替代 XML 或注解中逐个 Bean 的手动声明。
-
与相关组件的对比
组件 操作目标 执行阶段 典型用途 BeanFactoryPostProcessor
BeanDefinition Bean 实例化前 修改 Bean 定义属性(如 lazyInit) BeanPostProcessor
Bean 实例 Bean 初始化前后(实例已创建) AOP 代理、属性注入增强 FactoryBean
复杂 Bean 创建逻辑 Bean 实例化阶段 自定义复杂对象的实例化过程
@Lazy应用场景
- 优点:减少启动时间,节省资源。
- 缺点:首次调用时可能产生延迟,增加调试难度。
应用场景包括优化启动时间、处理资源消耗大的Bean和解决循环依赖。
- 优化启动速度(减少初始化耗时 Bean)
- 处理资源密集型对象(如数据库连接池)
- 解决循环依赖(配合构造器注入)
注意事项
- 默认单例模式下有效,原型 Bean 每次都会重新初始化。
- 避免与其他作用域注解(如
@Scope
)冲突。
- 性能权衡:全局启用延迟加载可能导致首次请求响应延迟,需结合实际场景选择。
- Bean 依赖冲突:若两个延迟加载的 Bean 存在依赖关系,可能引发初始化顺序问题。
- 框架整合:MyBatis 等框架通过
MapperScannerConfigurer
(本质为BeanFactoryPostProcessor
)动态注册 Mapper 接口,类似机制可参考。
代码案例
@Configuration
public class AppConfig {
@Bean
@Lazy // 延迟初始化
public DataSource dataSource() {
return new HikariDataSource();
}
}
延迟加载数据库连接池HikariDataSource。