感谢所有人(尤其是 Espen,他付出了很多努力向我展示了 Spring 中的各种选项)。
最后我自己找到了一个不需要Spring配置的解决方案。
我点击了 Stephen C 的链接,然后在该组线程中找到了对 SimpleBeanInfo 类的引用。此类允许用户编写自己的 bean 方法解析代码,方法是将另一个类放置在与具有非标准 setter/getter 的类相同的包中,以覆盖在类名上附加 'BeanInfo' 的逻辑并实现 'BeanInfo ' 界面。
然后我在谷歌上进行了搜索,发现了这个为我指明方向的博客。博客上的解决方案非常基本,因此我将其填充为我的目的。
每个班级(使用流利的设置器)
public class MyComponentBeanInfo<T> extends SimpleBeanInfo {
private final static Class<?> _clazz = MyComponent.class;
PropertyDescriptor[] _properties = null;
public synchronized PropertyDescriptor[] getPropertyDescriptors() {
if (_properties == null) {
_properties = Helpers.getPropertyDescriptionsIncludingFluentSetters(_clazz);
}
return _properties;
}
public BeanDescriptor getBeanDescriptor() {
return new BeanDescriptor(_clazz);
}
}
PropertyDescriptor 生成方法
public static PropertyDescriptor[] getPropertyDescriptionsIncludingFluentSetters( Class<?> clazz) {
Map<String,Method> getterMethodMap = new HashMap<String,Method>();
Map<String,Method> setterMethodMap = new HashMap<String,Method>();
Set<String> allProperties = new HashSet<String>();
PropertyDescriptor[] properties = null;
try {
Method[] methods = clazz.getMethods();
for (Method m : methods) {
String name = m.getName();
boolean isSetter = m.getParameterTypes().length == 1 && name.length() > 3 && name.substring(0,3).equals("set") && name.charAt(3) >= 'A' && name.charAt(3) <= 'Z';
boolean isGetter = (!isSetter) && m.getParameterTypes().length == 0 && name.length() > 3 && name.substring(0,3).equals("get") && name.charAt(3) >= 'A' && name.charAt(3) <= 'Z';
if (isSetter || isGetter) {
name = name.substring(3);
name = name.length() > 1
? name.substring(0,1).toLowerCase() + name.substring(1)
: name.toLowerCase();
if (isSetter) {
setterMethodMap.put(name, m);
} else {
getterMethodMap.put(name, m);
}
allProperties.add(name);
}
}
properties = new PropertyDescriptor[allProperties.size()];
Iterator<String> iterator = allProperties.iterator();
for (int i=0; i < allProperties.size(); i++) {
String propertyName = iterator.next();
Method readMethod = getterMethodMap.get(propertyName);
Method writeMethod = setterMethodMap.get(propertyName);
properties[i] = new PropertyDescriptor(propertyName, readMethod, writeMethod);
}
} catch (IntrospectionException e) {
throw new RuntimeException(e.toString(), e);
}
return properties;
}
这种方法的优点:
- 没有自定义弹簧配置(Spring 不知道非标准设置器并将它们视为正常)。不依赖于任何 Spring .jar 文件,但可以从 Spring 访问。
- 只是似乎工作。
这种方法的缺点:
- 我必须使用非标准设置器为我的所有 API 类创建一个 BeanInfo 类。幸运的是,只有大约 10 个这样的类,并且通过将方法解析逻辑移动到一个单独的类中,我只有一个地方需要维护。
结束的想法
在我看来,Spring 应该原生处理 fluent setter,它们不会伤害任何人,它应该忽略返回值。
通过要求 setter 严格无效,它迫使我编写了比我需要的更多的样板代码。我很欣赏 Bean 规范,但是即使不使用标准 bean 解析器,使用反射也很容易解决 bean,因此 Spring 应该提供自己的 bean 解析器选项来处理这种情况。
无论如何,将标准机制保留为默认值,但提供单行配置选项。我期待未来的版本可以选择放宽。