一个Spring Bean配置文件注入时的异常:TypeMismatchException

异常堆栈:

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.concurrent.ConcurrentHashMap] for property 'handlerNameHashMap'; nested exception is java.lang.IllegalArgumentException: Cannot convert value of type [java.util.LinkedHashMap] to required type [java.util.concurrent.ConcurrentHashMap] for property 'handlerNameHashMap': no matching editors or conversion strategy found`

这个异常时我在项目的配置文件注册一个工厂类之后,部署时抛出来的。

我的工厂类配置文件:

<!-- handler工厂 -->
    <bean id="handlerFactory" class="com.taobao.wmpevent.server.handler.HandlerFactory">
        <property name="handlerNameHashMap" >
            <map>
                <entry key="ORDER_STATUS" value-ref="saleOrderEventHandler"/>
                <entry key="PACKAGE_STATUS" value-ref="packageEventHandler"/>
            </map>
        </property>
    </bean>

我的工厂类:

public class HandlerFactory {

    private static ConcurrentHashMap<String, BaseHandler> handlerNameHashMap=new ConcurrentHashMap<String, BaseHandler>();
    ....

起先看到这个还以为我的Spring版本过低(2.5.6),然后就去对比了下也没发现差异,然后就去跟了下代码。
异常是在这段代码抛出的:

if (!ClassUtils.isAssignableValue(requiredType, convertedValue)) {
    // Definitely doesn't match: throw IllegalArgumentException.
    StringBuffer msg = new StringBuffer();
    msg.append("Cannot convert value of type [").append(ClassUtils.getDescriptiveType(newValue));
    msg.append("] to required type [").append(ClassUtils.getQualifiedName(requiredType)).append("]");
    if (propertyName != null) {
        msg.append(" for property '" + propertyName + "'");
    }
    if (editor != null) {
        msg.append(": PropertyEditor [" + editor.getClass().getName() + "] returned inappropriate value");
    }
    else {
        msg.append(": no matching editors or conversion strategy found");
    }
    throw new IllegalArgumentException(msg.toString());
}

上面的if语句里的requiredType是我要转换的ConcurrentHashMap,convertedValue这个是在方法的开始赋值的:

protected Object convertIfNecessary(
            String propertyName, Object oldValue, Object newValue, Class requiredType,
            PropertyDescriptor descriptor, MethodParameter methodParam)
            throws IllegalArgumentException {

        Object convertedValue = newValue;

然后沿着这个方法的调用链追溯,一直到AbstractAutowireCapableBeanFactory类的applyPropertyValues方法时才看到:

    String propertyName = pv.getName();
    Object originalValue = pv.getValue();
    Object resolvedValue = valueResolver.resolveValueIfNecessary(pv, originalValue);
    Object convertedValue = resolvedValue;
    boolean convertible = bw.isWritableProperty(propertyName) &&
                        !PropertyAccessorUtils.isNestedOrIndexedProperty(propertyName);
    if (convertible) {
        convertedValue = convertForProperty(resolvedValue, propertyName, bw, converter);
    }

最后一行代码的resolvedValue值就是上面我们提到的newValue,这个值是在resolveValueIfNecessary这个方法创建的:

    else if (value instanceof ManagedMap) {
            // May need to resolve contained runtime references.
            return resolveManagedMap(argName, (Map) value);
    }
    /**
     * For each element in the ManagedMap, resolve reference if necessary.
     */
    private Map resolveManagedMap(Object argName, Map mm) {
        Map resolved = new LinkedHashMap(mm.size());
        Iterator it = mm.entrySet().iterator();
        while (it.hasNext()) {
            Map.Entry entry = (Map.Entry) it.next();
            Object resolvedKey = resolveValueIfNecessary(argName, entry.getKey());
            Object resolvedValue = resolveValueIfNecessary(
                    argName + " with key " + BeanWrapper.PROPERTY_KEY_PREFIX + entry.getKey() + BeanWrapper.PROPERTY_KEY_SUFFIX,
                    entry.getValue());
            resolved.put(resolvedKey, resolvedValue);
        }
        return resolved;
    }

看到这里才明白堆栈里的Linked HashMap就是这里创建的,它当然不能转换成我需要的ConcurrentHashMap了。

于是我就纳闷了,难道就不能注入ConcurrentHashMap了,应该会有解决方案的吧,搜索了下,果然天无绝人之路啊!

Well ofcourse you get an error….

ConcurrentHashMap isn’t a LinkedHashMap and vice versa…

Also you should be programming to a Map instead of a concrete
implementation that way it wouldn’t matter what you inject, A HashMap
a LinkedHashMap or a ConcurrentHashMap all would work.

The map element generates a LinkedHashMap by default if you want to
create another one specify it with the targetMapClass property.

这是在一个帖子里看到的答案,顺着targetMapClass 这个关键词就摸到瓜了。

Spring中 ‘MapFactoryBean‘ 类给开发者提供了在Spring配置文件中创建具体的Map集合类的方法.

这个类的源码在这里可以看到:
http://dynaspring.googlecode.com/svn/trunk/src/dynaspring/support/MapFactoryBean.java

重新修改我的配置文件:

    <!-- handler工厂 -->
    <bean id="handlerFactory" class="com.taobao.wmpevent.server.handler.HandlerFactory">
        <property name="handlerNameHashMap" >
            <bean class="org.springframework.beans.factory.config.MapFactoryBean">
                <property name="targetMapClass">
                    <value>java.util.concurrent.ConcurrentHashMap</value>
                </property>
                <property name="sourceMap">
                    <map>
                        <entry key="ORDER_STATUS" value-ref="saleOrderEventHandler"/>
                        <entry key="PACKAGE_STATUS" value-ref="packageEventHandler"/>
                    </map>
                </property>
            </bean>
        </property>
    </bean>

部署时就不抛异常了。

Caused by: org.springframework.beans.TypeMismatchException一个Spring框架引发的异常。该异常通常在应用程序中出现,表示在自动装配(autowiring)依赖项类型不匹配。 具体来说,当Spring容器尝试将一个bean注入到另一个bean,它会检查它们的类型是否匹配。如果类型不匹配,就会抛出TypeMismatchException异常。 这个异常的出现可能由多种原因引起,比如: 1. 在配置文件中指定的bean类型与实际的bean类型不匹配。 2. 在注解中指定的依赖类型与实际的依赖类型不匹配。 3. 使用了错误的自动装配模式。 要解决这个问题,你可以按照以下步骤进行操作: 1. 检查配置文件或注解中的bean定义,确保指定的类型与实际的类型匹配。 2. 检查是否存在其他相同名称但类型不匹配的bean定义。 3. 检查是否使用了正确的自动装配模式,比如按名称(byName)或按类型(byType)进行装配。 通过对配置文件和代码的仔细检查,你应该能够找到并解决引发TypeMismatchException异常的问题。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [错误TypeMismatchException: Failed to convert property value of type [java.lang解决与原因?](https://blog.csdn.net/luo609630199/article/details/82821758)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] - *2* [SpringBoot启动报错:org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating...](https://blog.csdn.net/Faker_News/article/details/111710850)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] - *3* [Caused by: java.lang.ClassNotFoundException: org.apache.commons.collections.Transformer异常](https://download.csdn.net/download/weixin_38642864/12723222)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值