Kotlin与Kodein入门:如何将单例实例传入构造函数?
解决Kodein中获取单例实例注入构造函数的问题
嘿,刚接触Kotlin和Kodein遇到这种问题很正常,我来帮你理清楚怎么搞定~
你提到想用DKodein避免懒加载,这个思路方向是对的,但首先得明确Kodein里绑定单例的两种模式:默认的singleton是懒加载的,只有第一次获取实例时才会初始化;如果需要实例在容器启动时就创建(非懒加载),得用eagerSingleton。不过不管哪种模式,只要正确获取实例,都能传入构造函数。
先给你补全并修正代码:
// 先创建Kodein容器实例 val kodein = Kodein { // 用eagerSingleton让实例在容器初始化时就创建(非懒加载) bind<DataSource>() with eagerSingleton { val config = HikariConfig().apply { jdbcUrl = "jdbc:postgresql://localhost:5432/mydb" username = "username" password = "your_db_password" // 记得补全数据库密码 // 这里还可以加一些Hikari连接池的配置,比如最大连接数、超时时间等 } HikariDataSource(config) // 返回真正的DataSource实例 } } // 通过DKodein直接获取实例(kodein.direct就是DKodein实例) val dataSource: DataSource = kodein.direct.instance() // 现在就可以把这个实例传入需要它的构造函数了,比如: val myBusinessService = MyBusinessService(dataSource)
再给你划几个重点:
singletonvseagerSingleton:- 如果你能接受实例在第一次使用时才初始化,用
singleton就够了,它会保证全局唯一; - 如果像数据库连接池这种需要提前初始化的资源,就用
eagerSingleton,容器一启动就创建好实例。
- 如果你能接受实例在第一次使用时才初始化,用
DKodein的作用:
kodein.direct就是获取直接注入的入口,它允许你手动调用instance()拿到绑定的对象,完全适合你这种要手动传入构造函数的场景。更优雅的构造函数注入方式:
如果你的业务类也是由Kodein管理的,其实可以不用手动传实例,让Kodein自动注入:
// 业务类,构造函数依赖DataSource class MyBusinessService(private val dataSource: DataSource) // 在Kodein容器里绑定业务类 val kodein = Kodein { bind<DataSource>() with eagerSingleton { /* ... */ } bind<MyBusinessService>() with singleton { MyBusinessService(instance()) } } // 获取业务类实例时,Kodein会自动把DataSource注入进去 val myService = kodein.direct.instance<MyBusinessService>()
这样就省了手动传递的步骤,更符合依赖注入的思想。
如果你之前拿不到实例,大概率是这几个原因:
- 数据库配置没补全(比如密码漏写),导致DataSource初始化失败;
- 绑定的类型和实际返回的实例类型不匹配;
- 用了懒加载的
singleton但还没触发实例创建(不过只要调用instance()就能拿到)。
内容的提问来源于stack exchange,提问作者Brian DiCasa
相关产品推荐
相关产品推荐

