繁体   English   中英

Spring bean创建失败。 setter的参数类型可以是getter的返回类型的父代吗?

[英]Spring bean creation failed. Can parameter type of the setter be parent of the return type of the getter?

从DBCP2创建数据源bean时,我遇到此异常。 例外是

由以下原因引起:org.springframework.beans.NotWritablePropertyException:Bean类[org.apache.commons.dbcp2.BasicDataSource]的无效属性'connectionInitSqls':Bean属性'connectionInitSqls'是不可写的或具有无效的setter方法。 setter的参数类型是否与getter的返回类型匹配?

这是我的bean配置

<bean id="fileStore_dataSource" class="org.apache.commons.dbcp2.BasicDataSource"
    destroy-method="close" lazy-init="true">
    <!-- Just that property which causes problem -->
    <property name="connectionInitSqls">
        <list>
            <value>#{filestore.jdbc.connectionInitSql}</value>
        </list>
    </property>

</bean>

这是BasicDataSource类中connectionInitSqls的设置程序和获取程序代码。 DBCP2的版本是2.1.1

private volatile List<String> connectionInitSqls;

public List<String> getConnectionInitSqls() {
    final List<String> result = connectionInitSqls;
    if (result == null) {
        return Collections.emptyList();
    }
    return result;
}

public void setConnectionInitSqls(final Collection<String> connectionInitSqls) {
    if (connectionInitSqls != null && connectionInitSqls.size() > 0) {
        ArrayList<String> newVal = null;
        for (final String s : connectionInitSqls) {
        if (s != null && s.trim().length() > 0) {
                if (newVal == null) {
                    newVal = new ArrayList<>();
                }
                newVal.add(s);
            }
        }
        this.connectionInitSqls = newVal;
    } else {
        this.connectionInitSqls = null;
    }
}

您可以看到setter中的参数是Collection,它是List的超级类型。 但是我不知道为什么春天不能实例化bean。 这是Spring问题还是DBCP2代码中的Bug? 我们可以在setter参数中指定父类型的属性吗? 我该如何解决这个问题? 任何帮助,将不胜感激。

尝试${代替#{

<property name="connectionInitSqls">
        <list>
            <value>${filestore.jdbc.connectionInitSql}</value>
        </list>
    </property>

Spring将使用反射来查找setter属性。 因此,由于属性类型(它将从getter方法getConnectionInitSqls中找到),它将使用setConnectionInitSqls和参数列表来查找setter,因此不会找到异常。

现在,异常消息是不言自明的。 请注意,该属性可能根本不存在。 Spring只能与getter和setter一起使用。 它使用getter方法的返回值类型(该方法很容易找到仅带有get且没有arg方法的前缀)来找到合适的setter方法。

Bean属性“ connectionInitSqls”不可写或具有无效的setter方法。 setter的参数类型是否与getter的返回类型匹配


您可以尝试使用MethodInvokingFactoryBean

<bean id="fileStore_dataSource" class="org.apache.commons.dbcp2.BasicDataSource"
    destroy-method="close" lazy-init="true">
</bean>

<bean id="customInjector"
    class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
    <property name="targetObject" ref="fileStore_dataSource" />
    <property name="targetMethod">
        <value>setConnectionInitSqls</value>
    </property>
    <property name="arguments">
        <list>
            <value>#{filestore.jdbc.connectionInitSql}</value>
        </list>
    </property>
</bean>


替代方式:
更喜欢这个,因为它是SAFER 原因是所有属性都在实例化阶段本身中设置。 然后在豆之间进行接线。 在前一种情况下,它可能易于出错,因为设置connectionInitSqls的时间是不同的,并且可能已经创建了连接(而无需查看BasicDataSource实现的内部)。

public class CustomBasicDataSource extends BasicDataSource{
    public void setConnectionInitSqls(List<String> connectionInitSqls) {
        super.setConnectionInitSqls(connectionInitSqls);
    }
}

用xml中的此类替换

<bean id="fileStore_dataSource"
    class="org.company.somepackage.CustomBasicDataSource" destroy-method="close" lazy-init="true">
  ...<!-- rest remain same-->
</bean>

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM