2011-12-01 79 views
7

我想用斯卡拉Spring。我知道Autowired可以和Scala類一起工作,但是我使用的是一個需要一個對象的web框架,我想向它注入一個dao。我想知道如何做到這一點?對不起,我對Scala很陌生,在此先感謝。如何在Scala對象中使用Spring Autowired(或手動連線)?

@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

爲什麼你需要一個對象在這裏? 無論如何'@Service class Hello {@Autowired var repo:Repository = _}' 應該可以正常工作,假設您已經配置了組件掃描或使用AnnotationConfigApplicationContext – OlegYch

回答

12

基本上,你有兩個問題:

  • 屬性應該是可變的,即var而不是val

  • 斯卡拉object的所有方法都是static,而春季預計的實例方法。實際上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> 

您可以@Autowired取代<property>,但不能因與上述單一實例的問題代替人工的bean聲明與@Service

參見:

+0

這很酷。我想知道是否有一種使用Spring 3.1的非xml方法。 – sourcedelica

+0

@ericacm:實際上,你可以創建一個@配置對象,並從它的@ Bean註釋的方法返回'UserRest $ .MODULE $'。它已經在Spring 3.0中可用。 – axtavt

+0

是的 - 好點。 – sourcedelica

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()注入的生命週期不會被彈簧控制的任何對象。例如,JPA實體等。

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將反射地指定給底層字段)。

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" /> 

的幾個注意事項:

  • 使用@Configuration保證您的伴侶對象是熱切自動裝配的
  • 使用@Bean def避免了必須處理嘈雜的名稱Scala賦予實現伴隨對象的類
  • VAL工作得很好,由戴維·格里菲斯提到
  • 沒有必要對Scala的@BeanProperty,春天理解斯卡拉性質開箱(我使用的是3.2.2)
0

https://stackoverflow.com/a/8344485/5479289,也可以使用工廠方法向Spring上下文添加scala 包對象以及scala 對象。編譯的包對象是通常的java類,名稱爲,因此可以將它添加到Spring上下文中。之後,你將擁有所有Spring的可能性此對象的內部,即@Autowired@Value,手動佈線等

測試包:

package my.module 

package object A { 
    def getInstance = this 

    @Autowired 
    private val b: B = null 
} 

而且Spring上下文XML是:

<beans ...> 
    ... 
    <bean id="a" class="my.module.A.package" factory-method="getInstance"/> 
    ... 
</beans> 
相關問題