我正在尝试创建一个扩展函数,其实现使用 Spring bean。通过在包的顶层定义扩展函数似乎不可能做到这一点。我试过这个:
@Component
class Converter {
companion object {
@Autowired
lateinit var transformer: Transformer
fun Class1.convert(): Class2 {
return Class2 (this, transformer.transform(someStringProperty))
}
}
}
Run Code Online (Sandbox Code Playgroud)
wheretransform是一个将某个字符串转换为另一个字符串的函数,并且Class1是某个具有someStringProperty属性的类。我希望其他类可以import pkg.Converter.Companion.convert然后能够使用x.convert()wherex是类型的对象Class1。
语法有效,x.convert()在其他类中使用编译正常。但它在运行时导致异常:kotlin.UninitializedPropertyAccessException: lateinit property transformer has not been initialized
看起来 Spring 没有自动装配变量,因为它位于伴随对象中,而不是实际的组件对象中。
注释伴随对象@Component不起作用。
我不认为Class1.convert直接在内部移动Converter会起作用,因为然后使用x.convert()将需要Converter对象的实例,并且我不知道如何使用扩展函数语法来做到这一点。
有什么办法可以做到这一点,还是必须放弃扩展函数语法?
扩展函数可以使用文件范围私有变量,并在组件的@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
}
Run Code Online (Sandbox Code Playgroud)
及其测试代码:
@RunWith(SpringRunner::class)
@ContextConfiguration(classes = [ClassOne::class])
class DependencyInjectionTest {
@Autowired
lateinit var autowiredConfiguration : ClassOne
@Test
fun testAccessComponentInExtension() {
Assert.assertEquals(autowiredConfiguration.value, c1.value)
}
}
Run Code Online (Sandbox Code Playgroud)
这是无法完成的,因为 Spring 中无法自动装配静态字段,如下所述:Can you use @Autowired with static fields?
有一些解决方法,但一般建议不要这样做。
话虽如此,如果您真的致力于使这个解决方案发挥作用,您可能会通过使用带有参数的单例来摆脱它,如本博客文章所示:https ://medium.com/@BladeCoder/kotlin-singletons-with-argument -194ef06edd9e。虽然坦率地说我认为这样一个复杂的解决方案会完全违背目的
| 归档时间: |
|
| 查看次数: |
4759 次 |
| 最近记录: |