我可以编写一个使用自动装配的Spring bean的Kotlin扩展函数吗?

时间:2017-10-06 00:50:29

标签: spring kotlin

我正在尝试创建一个扩展函数,其实现使用Spring bean。通过在包的顶层定义扩展函数似乎不可能做到这一点。我试过这个:

@Component
class Converter {

    companion object {
        @Autowired
        lateinit var transformer: Transformer

        fun Class1.convert(): Class2 {
            return Class2 (this, transformer.transform(someStringProperty))
        }
    }    
}

其中transform是将某些字符串转换为另一个字符串的函数,而Class1是某个具有someStringProperty属性的类。我希望其他类可以import pkg.Converter.Companion.convert然后能够使用x.convert() xClass1类型的对象。

语法有效,在其他类中使用x.convert()编译很好。但它会在运行时导致异常:kotlin.UninitializedPropertyAccessException: lateinit property transformer has not been initialized

看起来Spring并没有自动装配变量,因为它位于伴随对象中而不是实际的组件对象。

使用@Component注释随播广告对象不起作用。

我不认为直接在Class1.convert内移动Converter会有效,因为使用x.convert()会需要Converter对象的实例,而我不会请参阅扩展函数语法,了解如何执行此操作。

有没有办法实现这一点,还是我必须放弃扩展函数语法?

2 个答案:

答案 0 :(得分:3)

它无法完成,因为在Spring中无法自动连接静态字段,如下所述:Can you use @Autowired with static fields?

有一些解决方法,但一般建议不要这样做。

如果你真的致力于使这个解决方案发挥作用,你可以通过使用 Singleton with parameters 来解决这个问题,如本博客文章所示:https://medium.com/@BladeCoder/kotlin-singletons-with-argument-194ef06edd9e。虽然坦率地说我认为这样一个错综复杂的解决方案会彻底击败目的

答案 1 :(得分:1)

扩展功能可以使用文件范围私有变量,并且可以在 组件的@PostConstruct方法,将“ this”分配给私有变量。 这种设计将组件的依赖关系添加到扩展功能中, 现在它们都绑定到同一个私有变量。但是,如果他们都遇到相同的问题,我认为这是可以容忍的,而且似乎没有其他更好的方法。

@Component
public class ClassOne {
    var value = Random.nextInt()

    @PostConstruct
    private fun init() {
        c1 = this
    }
}

private lateinit var c1 : ClassOne
fun String.appendC1() : String {
    return this + c1.value
}

及其测试代码:

@RunWith(SpringRunner::class)
@ContextConfiguration(classes = [ClassOne::class])
class DependencyInjectionTest {
    @Autowired
    lateinit var autowiredConfiguration : ClassOne

    @Test
    fun testAccessComponentInExtension() {
        Assert.assertEquals(autowiredConfiguration.value, c1.value)
    }
}