gpt4 book ai didi

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

转载 作者:行者123 更新时间:2023-12-02 03:13:48 25 4
gpt4 key购买 nike

我在从 DBCP2 创建数据源 bean 时遇到此异常。异常(exception)是

Caused by: org.springframework.beans.NotWritablePropertyException: Invalid property 'connectionInitSqls' of bean class [org.apache.commons.dbcp2.BasicDataSource]: Bean property 'connectionInitSqls' is not writable or has an invalid setter method. Does the parameter type of the setter match the return type of the 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的setter和getter代码。 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的父类(super class)型。但我不知道为什么spring无法实例化bean。这是 Spring 问题还是 DBCP2 代码中的 Bug。我们可以在 setter 参数中给出属性的父类型吗?我该如何解决这个问题?任何帮助,将不胜感激。

最佳答案

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

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

Bean property 'connectionInitSqls' is not writable or has an invalid setter method. Does the parameter type of the setter match the return type of the 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>


替代方式:
更喜欢这个,因为它更安全。原因是所有属性都是在实例化阶段本身设置的。然后bean之间发生连接。在前一种情况下,它可能容易出错,因为设置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>

关于java - Spring bean 创建失败。 setter 的参数类型可以是 getter 返回类型的父级吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40636372/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com