kotlin 200行代码开发一个简化版Guice
今天本来打算继续完成系列文章的,不想仓促成文,还得好好构思一下。
今天花一点时间来介绍我的一个开源项目中用kotlin完成的一个mini guice的代码。
写这篇文章目的只为炫耀我最爱的kotlin是有多么简洁高效 :)
首先交代一下背景:
一、mynlp是一个由kotlin编写的中文nlp工具箱,当然里面出了分词还有其他炫酷功能,感兴趣可以了解一下。
二、guice是google开发的一个轻量级IOC容器框架。
三、mynlp中组件服务众多,必须一个IOC容器作为底层,spring太过庞大,早期选择了guice。
四、然后guice又依赖其他多个jar,我只是用到了guice部分功能
五、再然后强迫症犯了,半夜希望去除guice依赖,所以用kotlin原生模拟一个guice的api
所以就诞生了这个无依赖mini guice。
首先看一下mini guice的功能需求:
程序员看示例代码最开心了:
interface DbService{
}
class MysqlService : DbService {
}
@ImplementedBy(ElasticSearchService::class)
interface SearchService
class ElasticSearchService : SearchService {
}
interface BissService{
fun showService()
}
@Singleton
class BissServiceImpl(
val dbService: DbService,
val searchService: SearchService
):BissService{
override fun showService() {
println(dbService)
println(searchService)
}
}
@Singleton
class SprintUIController(val bissService: BissService){
fun hi(){
bissService.showService()
}
}
fun main() {
val models = ArrayList()
models += object : AbstractModule() {
override fun configure() {
bind(DbService::class.java).toInstance(MysqlService())
bind(BissService::class.java).toClass(BissServiceImpl::class.java)
}
}
val injector = createInjector(models)
val controller = injector.getInstance(SprintUIController::class.java)!!
controller.hi()
}
看起来和guice的api差不多吧
bind().toInstance() 和 bind().toClass 可以手动绑定。
@ImplementedBy可以在接口上直接指定绑定关系
@Singleton用来直接为单例
最方便的是构造函数自动注入:
class BissServiceImpl(
val dbService: DbService,
val searchService: SearchService
)
// 构造函数直接表明需要注入的接口即可
最后 getInstance 为你创建对象和对象的依赖。
当然这些需求能只是能满足内部简单需求,如循环依赖肯定会错误。
如果你的开源项目需要简单IOC支持,但是不想引入依赖,那么来试试吧!