如何在 kotlin 中使用像@Autowired 这样的春季注释?

在 Kotlin 有可能做类似的事情吗?

@Autowired
internal var mongoTemplate: MongoTemplate


@Autowired
internal var solrClient: SolrClient
103251 次浏览

是的,Kotlin 支持 Java 注释,大多数情况下与 Java 一样。 One gotcha is annotations on the primary constructor requires the explicit 'constructor' keyword:

来自 https://kotlinlang.org/docs/reference/annotations.html

如果需要对类的主构造函数进行注释,则需要将构造函数关键字添加到构造函数声明中,并在构造函数声明之前添加注释:

class Foo @Inject constructor(dependency: MyDependency) {
// ...
}

在 Spring 中执行依赖注入的推荐方法是构造函数注入:

@Component
class YourBean(
private val mongoTemplate: MongoTemplate,
private val solrClient: SolrClient
) {
// code
}

在 Spring 4.3之前,构造函数应该用 Autowired显式地注释:

@Component
class YourBean @Autowired constructor(
private val mongoTemplate: MongoTemplate,
private val solrClient: SolrClient
) {
// code
}

在极少数情况下,你可以使用现场注入,你可以借助 lateinit:

@Component
class YourBean {


@Autowired
private lateinit var mongoTemplate: MongoTemplate


@Autowired
private lateinit var solrClient: SolrClient
}

构造函数注入在 bean 创建时检查所有依赖项,所有注入的字段都是 val,另一方面 latinit 注入的字段只能是 var,并且运行时开销很小。要用构造函数测试类,不需要反射。

相关网址:

  1. 关于 Latinit 的文件
  2. 关于构造函数的文档
  3. 用 Kotlin 开发 Spring Boot 应用程序

您也可以通过构造函数自动连接依赖项。请记住使用 @Configuration, @Component, @Service等注释您的依赖项

import org.springframework.stereotype.Component


@Component
class Foo (private val dependency: MyDependency) {
//...
}

像这样

@Component class Girl( @Autowired var outfit: Outfit)

如果你想要属性注入,但不喜欢 lateinit var,这里是我的解决方案使用 属性委托:

private lateinit var ctx: ApplicationContext


@Component
private class CtxVarConfigurer : ApplicationContextAware {
override fun setApplicationContext(context: ApplicationContext) {
ctx = context
}
}


inline fun <reified T : Any> autowired(name: String? = null) = Autowired(T::class.java, name)


class Autowired<T : Any>(private val javaType: Class<T>, private val name: String?) {


private val value by lazy {
if (name == null) {
ctx.getBean(javaType)
} else {
ctx.getBean(name, javaType)
}
}


operator fun getValue(thisRef: Any?, property: KProperty<*>): T = value


}

Then you can use the much better by delegate syntax:

@Service
class MyService {


private val serviceToBeInjected: ServiceA by autowired()


private val ambiguousBean: AmbiguousService by autowired("qualifier")


}