2010-09-02 12 views
14

Ich habe diese Fabrik Klasse, die ich über Feder für die Laufzeitkonfiguration der Karte verdrahten will. Die Karte enthält ein Enum-Objekt und ein Standard-Pojo.Spring Framework: Befüllen einer Karte <Enum,Object> mit util: Karte

public class GenericEntityFactoryImpl implements GenericEntityFactory 
{ 
    private Map<IndexType,IEntity> indexEntityMap = null; 

    @Override 
    public IEntity getIndexEntity(IndexType index) { 
     return indexEntityMap.get(index); 
    } 

    public Map<IndexType, IEntity> getIndexEntityMap() { 
     return indexEntityMap; 
    } 

    public void setIndexEntityMap(Map<IndexType, IEntity> indexEntityMap) { 
     this.indexEntityMap = indexEntityMap; 
    } 
} 

Ich habe Probleme mit meinem Frühjahr util: Karte Verkabelung, da ich bin nicht sicher, wie man richtig einen bestimmten Aufzählungstyp verweisen, wenn der Schlüsselwert definiting. Die Bean Ref für den Kartenwert ist einfach. Alle Beispiele der Federkartenverkabelung scheinen davon auszugehen, dass der Schlüssel eine Zeichenkette ist!

<!-- the value object bean --> 
<bean id="cell" class="com.xx.xx.common.index.entity.CellEntity"/> 

<bean id="genericEntityFactory" class="com.xx.xx.common.index.GenericEntityFactoryImpl"> 
    <util:map 
     id="indexEntityMap" 
     map-class="java.util.HashMap" 
     key-type="com.xx.xx.common.index.IndexType" 
     value-type="com.xx.xx.common.index.GenericEntityFactoryImpl"> 
      <entry key="CELL"> 
       <ref bean="cell"/> 
      </entry> 
     </util:map> 
</bean> 

bearbeiten

So Refactoring i die Abbildung

<bean id="genericEntityFactory" class="com.xx.xx.common.index.GenericEntityFactoryImpl" > 
    <property name="indexEntityMap"> 
     <map > 
      <entry key="com.xx.xx.common.index.CELL"><ref bean="cell"/></entry> 
     </map> 
    </property> 
</bean> 

aber Annahme, dass der Frühling nicht intelligent sein ...

Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'genericEntityFactory' defined in class path resource [com/xx/xx/common/index/index-application-context.xml]: Initialization of bean failed; nested exception is org.springframework.beans.TypeMismatchException: Failed to convert property value of type [java.util.LinkedHashMap] to required type [java.util.Map] for property 'indexEntityMap'; nested exception is java.lang.IllegalArgumentException: Cannot convert value of type [java.lang.String] to required type [com.xx.xx.common.index.IndexType] for property 'indexEntityMap[com.xx.xx.common.index.CELL]': no matching editors or conversion strategy found 
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:480) 
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory$1.run(AbstractAutowireCapableBeanFactory.java:409) 
    at java.security.AccessController.doPrivileged(Native Method) 
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:380) 
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:264) 
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:221) 
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:261) 
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:185) 
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:164) 
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:429) 
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:729) 
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:381) 
    at org.springframework.test.context.support.AbstractGenericContextLoader.loadContext(AbstractGenericContextLoader.java:84) 
    at org.springframework.test.context.support.AbstractGenericContextLoader.loadContext(AbstractGenericContextLoader.java:42) 
    at org.springframework.test.context.TestContext.loadApplicationContext(TestContext.java:173) 
    at org.springframework.test.context.TestContext.getApplicationContext(TestContext.java:197) 
    ... 17 more 
Caused by: org.springframework.beans.TypeMismatchException: Failed to convert property value of type [java.util.LinkedHashMap] to required type [java.util.Map] for property 'indexEntityMap'; nested exception is java.lang.IllegalArgumentException: Cannot convert value of type [java.lang.String] to required type [com.xx.xx.common.index.IndexType] for property 'indexEntityMap[com.xx.xx.common.index.CELL]': no matching editors or conversion strategy found 
    at org.springframework.beans.BeanWrapperImpl.convertForProperty(BeanWrapperImpl.java:391) 
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.convertForProperty(AbstractAutowireCapableBeanFactory.java:1288) 
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyPropertyValues(AbstractAutowireCapableBeanFactory.java:1249) 
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1010) 
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:472) 
    ... 32 more 
Caused by: java.lang.IllegalArgumentException: Cannot convert value of type [java.lang.String] to required type [com.xx.xx.common.index.IndexType] for property 'indexEntityMap[com.xx.xx.common.index.CELL]': no matching editors or conversion strategy found 
    at org.springframework.beans.TypeConverterDelegate.convertIfNecessary(TypeConverterDelegate.java:219) 
    at org.springframework.beans.TypeConverterDelegate.convertToTypedMap(TypeConverterDelegate.java:508) 
    at org.springframework.beans.TypeConverterDelegate.convertIfNecessary(TypeConverterDelegate.java:194) 
    at org.springframework.beans.TypeConverterDelegate.convertIfNecessary(TypeConverterDelegate.java:138) 
    at org.springframework.beans.BeanWrapperImpl.convertForProperty(BeanWrapperImpl.java:386) 
    ... 36 more 

Antwort

12

fand ich eine Abhilfe, indem jeder ENUM definieren Ich plane hinzufügen, um die Karte als separate bean - sie in der Karte dank creating-spring-bean-from-java-5-enum

<bean id="CELL" class="com.xx.xx.common.index.IndexType" factory-method="valueOf"> 
    <constructor-arg> 
     <value>CELL</value> 
    </constructor-arg> 
</bean> 

<bean id="APN" class="com.xx.xx.common.index.IndexType" factory-method="valueOf"> 
    <constructor-arg> 
     <value>APN</value> 
    </constructor-arg> 
</bean> 

Nachdem die Aufzählungen definiert Ich kann sie Schlüssel-ref

<bean id="genericEntityFactory" class="com.xx.xx.common.index.GenericEntityFactoryImpl" > 
    <property name="indexEntityMap"> 
     <map> 
      <entry key-ref="CELL"><ref bean="cell"/></entry> 
      <entry key-ref="APN"><ref bean="apn"/></entry> 
     </map> 
    </property> 
</bean> 
-1

Ich denke, das ist das, was Sie brauchen. Hinweis: Ich glaube nicht, dass Sie die Attribute keytyp und value-type angeben müssen. Der Frühling sollte das schaffen können.

<bean id="genericEntityFactory" class="com.xx.xx.common.index.GenericEntityFactoryImpl"> 
    <property name="indexEntityMap" ref="indexEntityMapBean"/> 
</bean> 

<util:map id="indexEntityMapBean" 
     map-class="java.util.HashMap" 
     key-type="com.xx.xx.common.index.IndexType" 
     value-type="com.xx.xx.common.index.GenericEntityFactoryImpl"> 
      <entry key="com.xx.xx.common.index.IndexType.CELL"> 
       <ref bean="cell"/> 
      </entry> 
</util:map> 

Der einzige Grund, warum Sie <util:map statt der Reiniger annonomous <map> (siehe Abschnitt 3.3.3.3) ist, wenn man wollte Draht die gleiche Karte in mehrere Orte oder man wollte verwenden, um eine andere zugrunde liegende Karte Implementierung zB ConcurrentHashMap verwenden würde.

+0

(-1) Dies funktioniert nicht. Spring kann nicht herausfinden, wie der Schlüssel in ein Enum konvertiert wird. In meinem Fall bekomme ich: Fehler beim Erstellen Bean mit Name 'la': Fehler beim Konvertieren typisierten String-Wert für Bean-Eigenschaft 'sourceMap'; verschachtelte Ausnahme ist org.springframework.beans.ConversionNotSupportedException: Fehler beim Konvertieren des Werts vom Typ 'java.lang.String' in den erforderlichen Typ 'com.t.LayoutHolder $ LA'; geschachtelte Ausnahme ist java.lang.IllegalStateException: Wert des Typs [java.lang.String] kann nicht in den erforderlichen Typ [com.t.LayoutHolder $ LA] konvertiert werden: keine übereinstimmenden Editoren oder Konvertierungsstrategien gefunden – harschware

10

Hier ist eine alternative und kürzere Format:

<bean id="versionService" class="my.service.VersionService" 
     p:animalDAOMap-ref="animalDAOMap"/> 

<util:map id="p:animalDAOMap"> 
    <entry key="chicken" value-ref="chickenDAO"/> 
    <entry key="monkey" value-ref="monkeyDAO"/> 
    <entry key="pig" value-ref="pigDAO"/> 
</util:map> 

Fabrikat Sie sicher, dass der Namespace ich mit Spring 3.0+ hier

xmlns:util="http://www.springframework.org/schema/util" 

Und das Schema, wie Sie Got

+2

aber wo ist Ihre Enum? – emeraldjava

+0

+1 für Wert-Ref – hidralisk

0

den gleichen Fehler

http://www.springframework.org/schema/util 
http://www.springframework.org/schema/util/spring-util-3.0.xsd 

Durch die Art und Weise aufzunehmen. Ich konnte es vermeiden, indem ich mein Enum in eine Standalone-Datei umwandelte und mein Enum öffentlich machte.

Also meine

public enum EventType { INFO, ERROR } 

sind in

EventType.java

Auch habe ich nur ein Paket platziert, wenn das irgendwie wichtig ist. Ich Injizieren Abhängigkeit, die Art und Weise (durch xml von Konstruktor arg):

spring.xml:

<constructor-arg> 
    <map> 
     <entry key="INFO" value-ref="consoleEventLogger"></entry> 
     <entry key="ERROR" value-ref="combinedEventLogger"></entry> 
    </map> 
</constructor-arg> 

, die mit Federkern 4.3.6

für mich arbeiten ist

Ich glaube, es gibt eine Erklärung, die von der Reflexion und der internen Spring-Logik abhängt. Aber ich habe nicht viel Erfahrung mit Java, und das kann ich nicht bieten.

Verwandte Themen