如何在kotlin中使用@Autowired之类的spring注解?
How to use spring annotations like @Autowired in kotlin?
是否可以在 Kotlin 中执行以下操作?
@Autowired
internal var mongoTemplate: MongoTemplate
@Autowired
internal var solrClient: SolrClient
是的,java 注释在 Kotlin 中主要与在 Java 中一样受支持。
一个陷阱是主构造函数上的注释需要显式 'constructor' 关键字:
来自https://kotlinlang.org/docs/reference/annotations.html
If you need to annotate the primary constructor of a class, you need to add the constructor keyword to the constructor declaration, and add the annotations before it:
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
,另一方面,lateinit 注入的字段只能是 var
,并且运行时开销很小。要使用构造函数测试 class,您不需要反射。
链接:
您还可以通过构造函数自动装配依赖项。记得用 @Configuration, @Component, @Service
etc
注释你的依赖项
import org.springframework.stereotype.Component
@Component
class Foo (private val dependency: MyDependency) {
//...
}
那样
@Component class Girl( @Autowired var outfit: Outfit)
如果你想要 属性 注入但不喜欢 lateinit var
,这是我使用 property delegate 的解决方案:
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
}
然后你可以使用更好的 by
委托语法:
@Service
class MyService {
private val serviceToBeInjected: ServiceA by autowired()
private val ambiguousBean: AmbiguousService by autowired("qualifier")
}
是否可以在 Kotlin 中执行以下操作?
@Autowired
internal var mongoTemplate: MongoTemplate
@Autowired
internal var solrClient: SolrClient
是的,java 注释在 Kotlin 中主要与在 Java 中一样受支持。 一个陷阱是主构造函数上的注释需要显式 'constructor' 关键字:
来自https://kotlinlang.org/docs/reference/annotations.html
If you need to annotate the primary constructor of a class, you need to add the constructor keyword to the constructor declaration, and add the annotations before it:
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
,另一方面,lateinit 注入的字段只能是 var
,并且运行时开销很小。要使用构造函数测试 class,您不需要反射。
链接:
您还可以通过构造函数自动装配依赖项。记得用 @Configuration, @Component, @Service
etc
import org.springframework.stereotype.Component
@Component
class Foo (private val dependency: MyDependency) {
//...
}
那样
@Component class Girl( @Autowired var outfit: Outfit)
如果你想要 属性 注入但不喜欢 lateinit var
,这是我使用 property delegate 的解决方案:
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
}
然后你可以使用更好的 by
委托语法:
@Service
class MyService {
private val serviceToBeInjected: ServiceA by autowired()
private val ambiguousBean: AmbiguousService by autowired("qualifier")
}