我正在尝试将Spring与Scala一起使用。我知道Autowired可以使用Scala类,但我使用的是需要一个对象的Web框架,我想在其中注入一个dao。我想知道该怎么做?对不起,我对Scala很新,感谢提前。
@Service
object UserRest extends RestHelper {
@Autowired
@BeanProperty
val userRepository: UserRepository = null;
.....
}
<beans>
.....
<bean id="userRest" class="com.abc.rest.UserRest" >
<!--- this is my attempt to manually wire it --->
<property name="userRepository" ref="userRepository"/>
</bean>
</beans>
答案 0 :(得分:15)
基本上,你有两个问题:
属性应该是可变的,即var
而不是val
Scala object
的所有方法都是static
,而Spring需要实例方法。实际上,Scala在场景后面创建了一个名为UserRest$
的实例方法的类,你需要让它的单例实例UserRest$.MODULE$
可用于Spring。
Spring可以将配置应用于预先存在的单例实例,但它们应该由方法返回,而UserRest$.MODULE$
是一个字段。因此,您需要创建一个返回它的方法。
所以,这样的事情应该有效:
object UserRest extends RestHelper {
@BeanProperty
var userRepository: UserRepository = null;
def getInstance() = this
...
}
<bean id="userRest"
class="com.abc.rest.UserRest"
factory-method = "getInstance">
<property name="userRepository" ref="userRepository"/>
</bean>
您可以将<property>
替换为@Autowired
,但由于上述单例实例存在问题,无法用@Service
替换手动bean声明。
另见:
答案 1 :(得分:4)
所有实际需要的是将对象定义为类,而不是对象。那样Spring会实例化它。
@Service
object UserRest extends RestHelper {
@Autowired
@BeanProperty
val userRepository: UserRepository = null;
.....
}
<beans>
.....
<bean id="userRest" class="com.abc.rest.UserRest" >
<!--- this is my attempt to manually wire it --->
<property name="userRepository" ref="userRepository"/>
</bean>
</beans>
将“val”更改为“var”是不必要的(Spring使用反射,忽略了不变性)。我很确定@BeanProperty也是不必要的(Spring会反过来分配给底层字段)。
答案 2 :(得分:3)
axtavt的解决方案对我不起作用,但结合其他答案的不同建议我认为这是最优雅的解决方案:
object User {
@Autowired val repo: UserRepository = null
def instance() = this
}
@Configuration
class CompanionsConfig {
@Bean def UserCompanion = User.instance
}
<context:component-scan base-package="your-package" />
一些注意事项:
答案 3 :(得分:1)
我所做的是使用AutowiredAnnotationBeanPostProcessor在施工时注入对象。
例如:
object UserRest extends RestHelper {
@Autowired
var userRepository: UserRepository = _
AppConfig.inject(this)
}
@Configuration
class AppConfig extends ApplicationListener[ContextRefreshedEvent] {
// Set the autowiredAnnotationBeanPostProcessor when the Spring context is initialized
def onApplicationEvent(event: ContextRefreshedEvent) {
autowiredAnnotationBeanPostProcessor =
event.applicationContext.
getBean(AnnotationConfigUtils.AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME).
asInstanceOf[AutowiredAnnotationBeanPostProcessor]
}
}
object AppConfig {
var autowiredAnnotationBeanPostProcessor: AutowiredAnnotationBeanPostProcessor = null
def inject(obj: AnyRef) {
autowiredAnnotationBeanPostProcessor.processInjection(obj);
}
}
现在,您可以使用AppConfig.inject()来注入生命周期不受Spring控制的任何对象。例如,JPA实体等
答案 4 :(得分:1)
使用@Component或@Bean标记的类的正常自动装配可以使用上述方法。
但是如果你想自动连接一个扩展Jpa存储库的接口,那么确保Dao不是一个对象而是类。
例如:
DAO:
object dao{
@Autowired val repo: jpaRepo = null
}
这不起作用(测试过)。我的猜测是,因为它被定义为一个对象,在运行时使用repo作为空值进行实例化,因此无法自动装配jpa repo。
而是将其声明为类并使用@Component标记:
@Component
class dao{
@Autowired val repo: jpaRepo = null
}
它起作用,因为我们让spring来管理自动装配jpa repo的对象创建(@component)。
答案 5 :(得分:1)
以前的answears都没有为我工作,但是经过一番挣扎之后,我可以这样解决它:
public class XsDevice implements XsensDotDeviceCb, Serializable {
private MutableLiveData<ArrayList<Float>> accelerationData = new MutableLiveData<>();
public LiveData<ArrayList<Float>> freeAccDataLiveData = accelerationData;
...
@Override
public void onXsensDotDataChanged(String s, XsensDotData xsensDotData) {
ArrayList<Float> result = new ArrayList();
for (Float freeAcc: xsensDotData.getFreeAcc()) {
result.add(freeAcc);
}
accelerationData.postValue(result);
}
}
然后是对象:
@Service
class BeanUtil extends ApplicationContextAware {
def setApplicationContext(applicationContext: ApplicationContext): Unit = BeanUtil.context = applicationContext
}
object BeanUtil {
private var context: ApplicationContext = null
def getBean[T](beanClass: Class[T]): T = context.getBean(beanClass)
}
答案 6 :(得分:0)
除了https://stackoverflow.com/a/8344485/5479289之外,还可以使用工厂将scala 包对象添加到Spring上下文,以及scala 对象方法。编译的包对象通常是名为 package 的java类,因此可以将其添加到Spring上下文中。在此之后,您将拥有Spring的所有可能性,即 @Autowired , @Value ,手动布线等。
测试包:
package my.module
package object A {
def getInstance = this
@Autowired
private val b: B = null
}
Spring context xml是:
<beans ...>
...
<bean id="a" class="my.module.A.package" factory-method="getInstance"/>
...
</beans>
答案 7 :(得分:0)
我遇到了同样的问题。
我有很多服务,想从scala对象中调用这些@Autowired服务。
我尝试了以上所有方法,但都没有达到我的期望。
我有一个名为JobConfig.scala
的对象,我想自动装配TableResolver
类,而TableResolver
类本身可以自动装配许多其他类。
我的应用程序在spring boot和scala中。
src/main/resources/applicationContext.xml
文件。<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<bean id="jobId" class="package.JobConfig"
factory-method="getInstance">
</bean>
</beans>
XmlBeansConfig.scala
import org.springframework.context.annotation.{Configuration, ImportResource}
@Configuration
@ImportResource(value = Array("classpath*:applicationContext.xml"))
class XmlBeansConfig {
}
JobConfig.scala
内object JobConfig{
def getInstance = this
@Autowired
var tableResolver: TableResolver = _
}