Spring + Scala + 匿名块或 class
Spring + Scala + anonymous block or class
我不知道为什么,但如果实例变量文本是私有的,下面的 class 就不起作用,但如果我省略私有的,它就起作用了。
调试 "setField" 部分的测试我可以看到实例变量名称应该是 "text" 但它变成了 "com$test$SimpleTest$$text"
package com.test
import org.testng.annotations.Test
import org.springframework.test.util.ReflectionTestUtils
class SimpleTest {
private var text = ""
@Test
def testValueOfX(): Unit = {
val simpleTest = new SimpleTest
ReflectionTestUtils.setField(simpleTest,"text", "abc")
println(
Option[String](null)
.map(v => v + " 123")
.getOrElse {
simpleTest.text + " 321"
})
}
}
我认为问题出在 "getOrElse" 上,因为如果我也省略了,它会起作用。
Scala 编译器有权将您的私有字段编译成任何可用的 java 代码,因为它不会影响互操作性(如果您不采取任何技巧)。 Spring 的 setField
实际上做了这样的把戏,因为它使您的私有字段可访问(setAccessible(true)
内部)。 Public 字段总是按原样编译,以便从 Java 为您提供适当的接口。
使用 http://docs.scala-lang.org/overviews/reflection/environment-universes-mirrors.html to work with Scala reflection. Also this article 可能会有帮助。
Here 解释了为什么 scalac 使用另一个名称作为私有字段。
P.S。删除 .getOrElse(text)
使它起作用的原因是因为除了这段代码之外,您没有在任何地方使用 text
。
这个class只是为了说明问题,实际上和真正的class有很大的不同。所以我改变了策略,通过@Autowired 方法而不是@Autowired 字段接收实例。
package com.test
import org.testng.annotations.Test
import org.springframework.test.util.ReflectionTestUtils
class SimpleTest {
// item 1
private var text = ""
@Test
def testValueOfX(): Unit = {
val simpleTest = new SimpleTest
ReflectionTestUtils.invokeSetterMethod(simpleTest, "text", "abc")
println(
Option[String](null)
.map(v => v + " 123")
.getOrElse {
simpleTest.text + " 321"
})
}
// item 2
def setText(text: String): Unit = {
this.text = text
}
}
我没有在这个示例中使用@Autowired,但在真实的 class 中我是。因此,如果您需要获取实例,请按照以下说明进行操作。
项目 1 -> 如果我使用 @Autowired 它不起作用,因为就像说的那样 dk14 Scala 编译器有权将您的私有字段编译成任何工作 java代码。因此,编译器在编译 class
时更改字段名称
项目 2 -> 我在 setter 方法中添加了 @Autowired,它起作用了。
我不知道为什么,但如果实例变量文本是私有的,下面的 class 就不起作用,但如果我省略私有的,它就起作用了。
调试 "setField" 部分的测试我可以看到实例变量名称应该是 "text" 但它变成了 "com$test$SimpleTest$$text"
package com.test
import org.testng.annotations.Test
import org.springframework.test.util.ReflectionTestUtils
class SimpleTest {
private var text = ""
@Test
def testValueOfX(): Unit = {
val simpleTest = new SimpleTest
ReflectionTestUtils.setField(simpleTest,"text", "abc")
println(
Option[String](null)
.map(v => v + " 123")
.getOrElse {
simpleTest.text + " 321"
})
}
}
我认为问题出在 "getOrElse" 上,因为如果我也省略了,它会起作用。
Scala 编译器有权将您的私有字段编译成任何可用的 java 代码,因为它不会影响互操作性(如果您不采取任何技巧)。 Spring 的 setField
实际上做了这样的把戏,因为它使您的私有字段可访问(setAccessible(true)
内部)。 Public 字段总是按原样编译,以便从 Java 为您提供适当的接口。
使用 http://docs.scala-lang.org/overviews/reflection/environment-universes-mirrors.html to work with Scala reflection. Also this article 可能会有帮助。
Here 解释了为什么 scalac 使用另一个名称作为私有字段。
P.S。删除 .getOrElse(text)
使它起作用的原因是因为除了这段代码之外,您没有在任何地方使用 text
。
这个class只是为了说明问题,实际上和真正的class有很大的不同。所以我改变了策略,通过@Autowired 方法而不是@Autowired 字段接收实例。
package com.test
import org.testng.annotations.Test
import org.springframework.test.util.ReflectionTestUtils
class SimpleTest {
// item 1
private var text = ""
@Test
def testValueOfX(): Unit = {
val simpleTest = new SimpleTest
ReflectionTestUtils.invokeSetterMethod(simpleTest, "text", "abc")
println(
Option[String](null)
.map(v => v + " 123")
.getOrElse {
simpleTest.text + " 321"
})
}
// item 2
def setText(text: String): Unit = {
this.text = text
}
}
我没有在这个示例中使用@Autowired,但在真实的 class 中我是。因此,如果您需要获取实例,请按照以下说明进行操作。
项目 1 -> 如果我使用 @Autowired 它不起作用,因为就像说的那样 dk14 Scala 编译器有权将您的私有字段编译成任何工作 java代码。因此,编译器在编译 class
时更改字段名称项目 2 -> 我在 setter 方法中添加了 @Autowired,它起作用了。