简体   繁体   English

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

[英]How to use spring annotations like @Autowired in kotlin?

Is it possible to do something like following in Kotlin?是否可以在 Kotlin 中执行以下操作?

@Autowired
internal var mongoTemplate: MongoTemplate

@Autowired
internal var solrClient: SolrClient

Recommended approach to do Dependency Injection in Spring is constructor injection:在 Spring 中进行依赖注入的推荐方法是构造函数注入:

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

Prior to Spring 4.3 constructor should be explicitly annotated with Autowired :在 Spring 4.3 构造函数之前,应该使用Autowired显式注释:

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

In rare cases, you might like to use field injection, and you can do it with the help of lateinit :在极少数情况下,您可能喜欢使用字段注入,并且可以在lateinit的帮助下lateinit

@Component
class YourBean {

    @Autowired
    private lateinit var mongoTemplate: MongoTemplate

    @Autowired
    private lateinit var solrClient: SolrClient
}

Constructor injection checks all dependencies at bean creation time and all injected fields is val , at other hand lateinit injected fields can be only var , and have little runtime overhead.构造函数注入在 bean 创建时检查所有依赖项,所有注入的字段都是val ,另一方面,lateinit 注入的字段只能是var ,并且几乎没有运行时开销。 And to test class with constructor, you don't need reflection.并且要使用构造函数测试类,您不需要反射。

Links:链接:

  1. Documentation on lateinit 关于 lateinit 的文档
  2. Documentation on constructors 关于构造函数的文档
  3. Developing Spring Boot applications with Kotlin 使用 Kotlin 开发 Spring Boot 应用程序

Yes, java annotations are supported in Kotlin mostly as in Java.是的,与 Java 一样,Kotlin 主要支持 Java 注释。 One gotcha is annotations on the primary constructor requires the explicit 'constructor' keyword:一个问题是主构造函数上的注释需要显式的 'constructor' 关键字:

From https://kotlinlang.org/docs/reference/annotations.html来自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:如果需要对类的主构造函数进行注解,则需要在构造函数声明中添加constructor关键字,并在其前添加注解:

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

You can also autowire dependencies through the constructor.您还可以通过构造函数自动装配依赖项。 Remember to annotate your dependencies with @Configuration, @Component, @Service etc记得用@Configuration, @Component, @Service等注释你的依赖项

import org.springframework.stereotype.Component

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

像那样

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

If you want property injection but don't like lateinit var , here is my solution using property delegate :如果您想要属性注入但不喜欢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:然后你可以by委托语法更好地使用:

@Service
class MyService {

    private val serviceToBeInjected: ServiceA by autowired()

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

}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM