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