2010-09-02 27 views
14

Tôi có lớp nhà máy này, mà tôi muốn dây qua mùa xuân cho cấu hình thời gian chạy của bản đồ. Bản đồ chứa một đối tượng enum và pojo tiêu chuẩn.Spring Framework: Populating một bản đồ <Enum,Object> với util: bản đồ

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; 
    } 
} 

Tôi đang gặp sự cố với lò xo bản đồ, vì tôi không chắc chắn cách tham chiếu chính xác loại enum cụ thể khi xác định giá trị khóa. Các ref đậu cho giá trị bản đồ là dễ dàng. Tất cả các ví dụ về hệ thống dây điện bản đồ mùa xuân dường như giả định rằng chìa khóa là một chuỗi!

<!-- 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> 

Sửa

Vì vậy, tôi refactored ánh xạ

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

nhưng giả định rằng mùa xuân sẽ thông minh thất bại ...

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 

Trả lời

12

Tôi tìm thấy một workaround bằng cách định nghĩa mỗi enum tôi có kế hoạch để thêm vào bản đồ dưới dạng hạt riêng biệt - nhờ 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> 

Sau khi xác định enums tôi có thể họ key-ref chúng trong bản đồ

<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

Tôi nghĩ rằng đây là những gì bạn cần. Lưu ý tôi không nghĩ rằng bạn cần phải xác định các thuộc tính kiểu khóa và kiểu giá trị. Mùa xuân sẽ có thể làm việc đó.

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

Lý do duy nhất mà bạn sẽ sử dụng <util:map thay cho sạch annonomous <map> (xem phần 3.3.3.3) là nếu bạn muốn để dây cùng một bản đồ thành nhiều địa điểm hoặc bạn muốn sử dụng một cơ bản thực hiện bản đồ ví dụ ConcurrentHashMap khác nhau.

+0

(-1) Điều này không hiệu quả. Spring không thể tìm ra cách chuyển khóa thành enum. Trong trường hợp của tôi, tôi nhận được: Lỗi tạo bean với tên 'la': Lỗi chuyển đổi giá trị chuỗi đã nhập cho thuộc tính bean 'sourceMap'; ngoại lệ lồng nhau là org.springframework.beans.ConversionNotSupportedException: Không thể chuyển đổi giá trị của loại 'java.lang.String' thành loại bắt buộc 'com.t.LayoutHolder $ LA'; ngoại lệ lồng nhau là java.lang.IllegalStateException: Không thể chuyển đổi giá trị của loại [java.lang.String] thành loại bắt buộc [com.t.LayoutHolder $ LA]: không có trình chỉnh sửa phù hợp hoặc chiến lược chuyển đổi nào được tìm thấy – harschware

10

Dưới đây là một thay thế và định dạng ngắn:

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

Make chắc chắn bao gồm không gian tên

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

Và schema

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

Bằng cách này tôi đang sử dụng Spring 3.0+ đây

+2

nhưng enum của bạn ở đâu? – emeraldjava

+0

+1 cho giá trị-ref – hidralisk

0

Got những lỗi tương tự như bạn. Tôi đã có thể tránh nó bằng cách di chuyển enum của tôi vào tập tin độc lập và làm cho enum của tôi công khai.

Vì vậy, tôi

public enum EventType { INFO, ERROR } 

đang đặt trong

EventType.java

Ngoài ra tôi chỉ có một gói nếu có vấn đề nào đó. Tôi tiêm phụ thuộc theo cách đó (thông qua xml bởi constructor arg):

spring.xml:

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

Đó là làm việc cho tôi với mùa xuân-core 4.3.6

Tôi tin rằng có một lời giải thích, điều đó phụ thuộc vào sự phản chiếu và logic Spring nội bộ. Nhưng tôi không có nhiều kinh nghiệm về Java, và tôi không thể cung cấp điều đó.

Các vấn đề liên quan