java如何让Spring接受流畅(非类)的setter?
我有一个API,我正在把它变成一个内部DSL。因此,POJO中的大多数方法都会返回对此的引用,这样我就可以以声明的方式将方法链接在一起(语法糖)
myComponent
.setID("MyId")
.setProperty("One")
.setProperty2("Two")
.setAssociation(anotherComponent)
.execute();
我的API不依赖于Spring,但我希望通过对零参数构造函数、getter和setter的PoJo友好,使之成为“Spring友好型”。问题是,当我有一个非void返回类型时,Spring似乎没有检测到setter方法
这种返回类型在将命令链接在一起时非常方便,因此我不想破坏编程API,只是为了与Spring注入兼容
Spring中是否有允许我使用非无效设置器的设置
克里斯
# 1 楼答案
感谢所有人(尤其是埃斯彭,他花了很大的努力在春季向我展示了各种选择)
最后,我自己找到了一个不需要Spring配置的解决方案
我跟踪了Stephen C的链接,然后在这组线程中找到了对SimpleBeanifo类的引用。该类允许用户编写自己的bean方法解析代码,方法是将另一个类放在与该类相同的包中,并使用非标准setter/getter覆盖逻辑,将'BeanInfo'附加到类名上并实现'BeanInfo'接口
然后我在谷歌上搜索了一下,找到了这个blog为我指明了方向。博客上的解决方案非常基本,所以我根据自己的目的进行了补充
每堂课(有流利的二传手)
属性描述符生成方法
这种方法的优点:
这种方法的缺点:
结束思考
在我看来,Spring应该与流畅的二传手打交道,他们不会伤害任何人,应该忽略返回值
通过要求setter严格无效,它迫使我编写了比其他情况下需要的多得多的锅炉板代码。我很欣赏Bean规范,但是使用反射而不使用标准的Bean解析器,Bean解析是微不足道的,因此Spring应该提供自己的Bean解析器选项来处理这种情况
无论如何,将标准机制保留为默认机制,但提供单线配置选项。我期待着未来的版本,在那里这可能是随意放松
# 2 楼答案
简单的答案是否定的——没有这样的设置
Spring被设计为与JavaBeans规范兼容,这要求setter返回
void
有关讨论,请参阅this Spring Forums thread。论坛中提到的这个限制有可能解决,但没有简单的解决方案,我认为没有人真的报告说他们尝试过这个方法,并且它有效
# 3 楼答案
据我所知,没有简单的开关。Spring使用Beans约定,并期望有一个空白设置器。Spring通过BeanWrapper接口的实例在属性级别处理bean。默认实现BeanWrapperImpl使用内省,但您可以创建自己的修改版本,使用反射来查找与您的模式匹配的方法
编辑:看看Spring代码,
BeanWrapperImpl
是硬连接到bean工厂的,没有简单的方法可以用另一个实现来替换它。然而,由于spring使用内省,我们可以努力让java.beans.Introspector产生我们想要的结果。以下是减少疼痛的备选方案:BeanInfo
类BeanInfo
类插入到内省器中李>前两个选项可能并不适合你,因为它们涉及很多变化。更详细地探讨第三个选项:
要知道spring正在实例化哪些bean,请实现自己的BeanFactoryPostProcessor。这可以在BeanFactory使用所有bean定义之前查看它们。您的实现会迭代factor中的所有bean定义,并从每个定义中获取bean类。现在您知道了所有正在使用的类
有了一个类列表,你就可以开始为这些类创建自己的BeanInfos了。您可以使用内省器为每个类生成默认BeanInfo,这将为带有返回值设置器的属性提供只读属性。然后,基于原始BeanInfo创建一个新的BeanInfo,但PropertyDescriptor引用setter方法,即返回值setter
在为每个班级生成新的beanInfos后,你需要确保内省者在向你的班级索要beanInfos时返回这些信息。内省者有一个用于缓存beanInfos的私有地图。您可以通过反射来获取这个信息,启用access-setAccessible(true),并将BeanInfo实例添加到其中
当spring向内省者请求bean类的BeanInfo时,内省者返回修改后的BeanInfo,并使用返回值将setter方法映射到setter
# 4 楼答案
Spring也可以配置为Java configuration
举个例子:
你有一个很好的不可变对象。实际上,您已经实现了构建器模式
更新以回应Chris的评论:
我想这并不是你想要的,但是使用属性文件可以解决一些问题。请参见上面示例中的id字段
否则,可以使用Spring的FactoryBean模式:
使用FactoryBean,可以屏蔽配置,使其不受
getObject()
方法返回的对象的影响在XML配置中,配置FactoryBean实现。在本例中,使用
<constructor-arg />
元素# 5 楼答案
正如其他人所说,你可能失去的不仅仅是春天的友好。就JavaBeans而言,非void setter并不是真正的setter,其他各种工具(验证器、封送器、查看器、持久器,以及任何你能想到的工具)可能会使用Introspector和BeanInfo,它们期望setter为null
考虑到这一点,要求它们被称为
setX
有多灵活?Java中很多流畅的接口都使用withX
。如果您使用的是Eclipse,您可能可以创建一个代码生成模板来为您生成X getX()
、void setX(X x)
和X withX(X x)
。如果您使用的是其他一些codegen工具,我可以想象添加withX
fluent setter/getter方法也会很容易这个
with
词似乎有点奇怪,但当你看到它和构造函数在一起时,它读起来非常好一个这样的API是AWS SDK for Java,您可以参考它来获取示例。一个离题的警告是
boolean
getter可以被称为isX
,但是Boolean
getter必须被称为getX
# 6 楼答案
一个简单的建议是,习惯上不使用setter,而是使用属性名称本身。因此,有一个setter,并为构建器提供另一种方法: