Spring中能否在factory-method中链式调用方法创建Bean?
SomeObject.builder().build()) 当然可以做到!你提到的factory-method属性本身不支持直接写链式调用语法,但我们有两种实用的方案,不需要额外定义两个Bean就能实现需求:
方案一:使用MethodInvokingFactoryBean嵌套调用
Spring的MethodInvokingFactoryBean可以用来调用静态或实例方法,我们可以嵌套它来先获取Builder实例,再调用build()方法:
<bean id="fooBar" class="org.springframework.beans.factory.config.MethodInvokingFactoryBean"> <!-- 第一步:调用SomeObject.builder()获取Builder实例 --> <property name="targetObject"> <bean class="org.springframework.beans.factory.config.MethodInvokingFactoryBean"> <property name="targetClass" value="com.foo.bar.SomeObject"/> <property name="targetMethod" value="builder"/> </bean> </property> <!-- 第二步:调用Builder的build()方法得到最终Bean --> <property name="targetMethod" value="build"/> </bean>
这个配置的逻辑是:内层的MethodInvokingFactoryBean执行SomeObject.builder()拿到SomeObjectBuilder实例,外层的工厂Bean再调用该实例的build()方法,最终返回SomeObject对象。
方案二:使用SpEL表达式(推荐,Spring 3.0+)
如果你的Spring版本在3.0及以上,使用Spring表达式语言(SpEL)会更简洁,直接在factory-bean中用SpEL获取Builder实例,再配合factory-method指定build方法:
<bean id="fooBar" factory-bean="#{T(com.foo.bar.SomeObject).builder()}" factory-method="build"/>
这里的T()运算符用来访问指定类的静态方法,T(com.foo.bar.SomeObject).builder()会执行静态方法得到SomeObjectBuilder实例,然后factory-method="build"调用该实例的build()方法生成最终的Bean。
注意事项
关于你提到的SomeObjectBuilder是SomeObject内部的private static class:不用担心,因为builder()是SomeObject的public静态方法,它会返回SomeObjectBuilder实例,Spring通过反射可以正常调用该实例的build()方法,不受内部类访问修饰符的限制。
内容的提问来源于stack exchange,提问作者ayushgp

