0

0

如何实现一个支持依赖注入的 lazy 属性

舞姬之光

舞姬之光

发布时间:2026-01-27 19:34:39

|

170人浏览过

|

来源于php中文网

原创

Lazy不能直接用于依赖注入场景,因其初始化仅一次且不支持运行时传参,而依赖注入需每次访问时获取最新容器实例;应使用自定义委托或Spring原生@Lazy注解。

如何实现一个支持依赖注入的 lazy 属性

为什么 lazy 不能直接用在依赖注入场景

因为 lazy 初始化只执行一次,且不接受参数,而依赖注入通常需要运行时传入容器或上下文(比如 getBean(Class))。直接写 val service by lazy { ctx.getBean() } 会把 ctx 捕获为闭包变量——如果 ctx 尚未初始化或后续被替换,这个 lazy 值就会失效或抛 NullPointerException

Lazy + 自定义委托实现延迟获取

核心是把“获取逻辑”推迟到每次访问,而不是仅首次。Kotlin 的 Lazy 接口本身支持 getValue,我们可以封装一个委托,让它每次调用都查容器:

class InjectableLazy(private val getter: () -> T) : ReadOnlyProperty {
    override fun getValue(thisRef: Any?, property: KProperty<*>): T = getter()
}

// 使用
val service by InjectableLazy { applicationContext.getBean() }

这样既保持了语法简洁,又确保每次访问都走最新容器实例。注意:这不是真正“懒”,而是“按需获取”,适合依赖可能动态刷新的场景(如多上下文、测试 mock 替换)。

如果必须真懒且支持注入上下文,用带参的 lazy 工厂

标准 lazy 不支持传参,但你可以把容器作为外部依赖提前持有,再用 lazy 封装其 getBean 调用:

Video Summarization
Video Summarization

一款可以自动将长视频制作成短片的桌面软件

下载
  • private val ctx: ApplicationContext 必须在声明前已初始化(比如构造函数注入或 @Autowired 字段)
  • 然后写 val service by lazy { ctx.getBean() } —— 这才是真懒,且安全
  • ctx 是 lateinit,务必确保在第一次访问 service 前已完成赋值,否则触发 UninitializedPropertyAccessException

Spring 中更推荐用 @Lazy 注解而非手动 lazy 委托

Spring 原生的 @Lazy 是作用于 bean 创建时机的,和 Kotlin 的 lazy 完全不同层级。它让 Spring 在首次 getBean 时才实例化目标 bean,适用于单例 bean 之间的循环依赖或启动性能优化:

@Component
class MyService @Autowired constructor(@Lazy private val heavyDep: HeavyDependency)

这种写法由 Spring 容器控制生命周期,比手动委托更可靠;手动 lazy 委托只影响属性访问行为,不改变 bean 实例化策略。混用两者容易造成语义混淆,比如以为 @Lazy + by lazy 是双重懒加载,其实它们解决的是完全不同的问题。

真正难处理的是跨上下文、非 Spring 管理对象里的 lazy 属性——这时候必须自己控制获取时机和上下文有效性,稍有不慎就拿到过期引用或空指针。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
spring框架介绍
spring框架介绍

本专题整合了spring框架相关内容,想了解更多详细内容,请阅读专题下面的文章。

112

2025.08.06

Java Spring Security 与认证授权
Java Spring Security 与认证授权

本专题系统讲解 Java Spring Security 框架在认证与授权中的应用,涵盖用户身份验证、权限控制、JWT与OAuth2实现、跨站请求伪造(CSRF)防护、会话管理与安全漏洞防范。通过实际项目案例,帮助学习者掌握如何 使用 Spring Security 实现高安全性认证与授权机制,提升 Web 应用的安全性与用户数据保护。

28

2026.01.26

硬盘接口类型介绍
硬盘接口类型介绍

硬盘接口类型有IDE、SATA、SCSI、Fibre Channel、USB、eSATA、mSATA、PCIe等等。详细介绍:1、IDE接口是一种并行接口,主要用于连接硬盘和光驱等设备,它主要有两种类型:ATA和ATAPI,IDE接口已经逐渐被SATA接口;2、SATA接口是一种串行接口,相较于IDE接口,它具有更高的传输速度、更低的功耗和更小的体积;3、SCSI接口等等。

1099

2023.10.19

PHP接口编写教程
PHP接口编写教程

本专题整合了PHP接口编写教程,阅读专题下面的文章了解更多详细内容。

189

2025.10.17

php8.4实现接口限流的教程
php8.4实现接口限流的教程

PHP8.4本身不内置限流功能,需借助Redis(令牌桶)或Swoole(漏桶)实现;文件锁因I/O瓶颈、无跨机共享、秒级精度等缺陷不适用高并发场景。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

1423

2025.12.29

java接口相关教程
java接口相关教程

本专题整合了java接口相关内容,阅读专题下面的文章了解更多详细内容。

17

2026.01.19

class在c语言中的意思
class在c语言中的意思

在C语言中,"class" 是一个关键字,用于定义一个类。想了解更多class的相关内容,可以阅读本专题下面的文章。

469

2024.01.03

python中class的含义
python中class的含义

本专题整合了python中class的相关内容,阅读专题下面的文章了解更多详细内容。

13

2025.12.06

Python 自然语言处理(NLP)基础与实战
Python 自然语言处理(NLP)基础与实战

本专题系统讲解 Python 在自然语言处理(NLP)领域的基础方法与实战应用,涵盖文本预处理(分词、去停用词)、词性标注、命名实体识别、关键词提取、情感分析,以及常用 NLP 库(NLTK、spaCy)的核心用法。通过真实文本案例,帮助学习者掌握 使用 Python 进行文本分析与语言数据处理的完整流程,适用于内容分析、舆情监测与智能文本应用场景。

10

2026.01.27

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Java 教程
Java 教程

共578课时 | 52.1万人学习

国外Web开发全栈课程全集
国外Web开发全栈课程全集

共12课时 | 1.0万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号