2011-12-01 14 views
7

私はScalaでSpringを使用しようとしています。私はScalaクラスのAutowiredワークを知っていますが、オブジェクトを必要とする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

は基本的には、次の2つの問題を抱えて:春は、インスタンスメソッドを期待するのに対し、プロパティではなくval

  • よりすなわちvar、変更可能でなければなりませんスカラ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>を置き換えることができますが、原因上記のシングルトンインスタンスに問題に@Serviceと手動のBean宣言を置き換えることはできません。

    も参照してください:

  • +0

    これはかなりクールです。私はSpring 3.1でそれを行う非XMLメソッドがあるのだろうかと思います。 – sourcedelica

    +0

    @ericacm:実際には、 '@ Configuration'オブジェクトを作成し、その' @ Bean'-annotatedメソッドから '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はコンパニオンオブジェクトを実装するクラスに与えます
    • ヴァルデイブ・グリフィスで述べたようにScalaの@BeanPropertyの必要がない
    • 、うまく動作しますが、春には(私は3.2.2を使用しています)箱から出してScalaの性質を理解し
    0

    に加え、 https://stackoverflow.com/a/8344485/5479289、scala パッケージオブジェクトをSpringコンテキストに加え、scala オブジェクトをファクトリメソッドを使用して追加することもできます。コンパイルされたパッケージオブジェクトはパッケージという通常のJavaクラスであるため、Springのコンテキストに追加することができます。その後、あなたはすなわち、このオブジェクト内のすべてのSpringの可能性を持つことになります@Autowired、@value、マニュアル配線など

    テストパッケージ:

    package my.module 
    
    package object A { 
        def getInstance = this 
    
        @Autowired 
        private val b: B = null 
    } 
    

    と春コンテキストXMLは次のとおりです。

    <beans ...> 
        ... 
        <bean id="a" class="my.module.A.package" factory-method="getInstance"/> 
        ... 
    </beans> 
    
    関連する問題