2011-10-10 5 views
2

Cela peut être fait en utilisant une enveloppe de conversion:Spring: Injecter une liste Scala

import scala.collection.JavaConversions._ 

object ListConverter { 

    def toScalaList(jlist: java.util.List[AnyRef]) = { 
    jlist.toList 
    } 
} 

qui utilise un implicit def asScalaBuffer dans JavaConversions pour retourner une liste Scala. Ensuite, je peux faire la injectable liste comme:

<bean id="someItems" class="my.package.ListConverter" factory-method="toScalaList"> 
    <constructor-arg type="java.util.List"> 
     <util:list> 
      <ref bean="itemOne"/> 
      <ref bean="itemTwo"/> 
     </util:list> 
    </constructor-arg> 
</bean> 

Je voudrais trouver un moyen plus propre de le faire

Je ne peux pas vraiment utiliser JavaConversions directement comme un appel d'usine statique:

<bean id="someItems" class="scala.collection.JavaConversions" factory-method="asScalaBuffer">...</bean> 

Puisqu'un implicit def n'est pas vraiment une méthode statique dans un univers Java.

P.S. Pour le sortir du chemin .. Je sais qu'il y a beaucoup d'amateurs de config pilotés par annotation, mais je ne suis pas l'un d'eux, et ce n'est pas une solution que je cherche: J'aime mon XML pour Spring configs, et J'aime Spring à DI Scala

Répondre

3

Si vous souhaitez convertir un java.util.List en un scala List, vous devrez fournir votre propre méthode de conversion/usine car aucune méthode de ce type n'existe.

JavaConversions.asScalaBuffer peut être référencée exactement comme vous l'avez fait dans votre définition XML car le compilateur Scala génère des méthodes de redirecteur statique vers l'instance object à moins que vous ne lui disiez de ne pas le faire. Le problème ici est réellement en fait que cette méthode renvoie un scala.collection.mutable.Buffer que vous avez encore à convertir en List.

Une alternative consiste à accepter une instance de Seq[A] à injecter. Cela fonctionnera car Buffer[A] étend Seq[A] - mais vous devez être conscient que vous injectez un wrapper autour de l'instance (éventuellement mutable) java.util.List<A> alors.

+0

oui, fait le tour, je ne sais pas pourquoi il ne compilait pas avant, mais alors IntelliJ Scala plugin le fait parfois .. Une bonne idée de l'utilisation de Seq [A] au lieu de List [A] => ne préconise pas forcément un type de collection fort, mais dans mon cas, cela n'a pas vraiment d'importance qu'il s'agisse d'un List ou d'un Seq. Je vous remercie. – tolitius

1

Si votre ListConverter était un object plutôt qu'un class, ne serait pas toScalaList être acceptée comme une méthode statique?

+0

Oui, c'est aussi quelque chose que j'ai essayé, qui fonctionne. Il ne se sent pas propre à avoir un wrapper (ListConverter) autour d'un wrapper (JavaConversions) pour injecter une liste. – tolitius

+0

J'ai édité la question pour incorporer votre suggestion, car _question_ a l'air beaucoup plus propre avec elle, et vous a voté. Je vous remercie. – tolitius

0

Votre plus gros problème est que, dans les coulisses, Spring est intrinsèquement non typé. Cette liste que vous essayez d'injecter commence en List<String> avant que Spring ne détermine le type correct de la propriété/propriété cible. Il peut le faire car le type correspondant est conservé dans le bytecode (même s'il est effacé sur la JVM), cela ne fonctionnera pas dans le cas d'une injection dans des méthodes génériques. Dans d'autres cas, il peut déterminer le type d'une collection en inspectant des éléments. Il habituellement obtient ce droit, selon combien de polymorphisme est impliqué.

Bien sûr, toute cette logique est entièrement basée sur java.util.Collection et les sous-classes, donc les types de collection de Scala ne peuvent tout simplement pas rejoindre la partie.

Vous avez trois solutions ici:

  1. Apprendre à aimer l'injection axée sur l'annotation. Vous ne serez pas mordu par le faible-typage insidieux.

  2. Créez une surcharge de la méthode setter ou un constructeur auxiliaire prenant des types de collection Java équivalents. Ensuite, utilisez collection.JavaConverters pour gérer la conversion. Le printemps est alors heureux, car il est toujours dans sa zone de confort Java seulement.

  3. (mon préféré) Cessez d'utiliser Spring

Vous êtes assuré d'exécuter éventuellement un problème avec votre convertisseur, cela se produira à peu près au moment où vous découvrez la nécessité de faire face à la non-concordance de parité entre les primitives boxed et unboxed.

Questions connexes