Java Spring和在运行时将参数传递给工厂方法
方法context.getBean(名称,用户)的文档中说 允许指定显式构造函数参数/工厂方法 论据 但无论我做什么(尝试了一切),在初始化期间加载bean时,我都会使用最符合逻辑的设置:Java Spring和在运行时将参数传递给工厂方法,java,spring,factory-method,Java,Spring,Factory Method,方法context.getBean(名称,用户)的文档中说 允许指定显式构造函数参数/工厂方法 论据 但无论我做什么(尝试了一切),在初始化期间加载bean时,我都会使用最符合逻辑的设置: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'fileValidator' defined in PortletContext resource [/WEB-IN
org.springframework.beans.factory.UnsatisfiedDependencyException:
Error creating bean with name 'fileValidator' defined in
PortletContext resource
[/WEB-INF/classes/context/customer-form-portlet.xml]: Unsatisfied
dependency expressed through constructor argument with index 0 of type
[com.liferay.portal.model.User]: Ambiguous factory method argument
types - did you specify the correct bean references as factory method
arguments?
org.springframework.beans.factory.UnsatisfiedDependencyException:
Error creating bean with name 'fileValidator' defined in
PortletContext resource
[/WEB-INF/classes/context/customer-form-portlet.xml]: Unsatisfied
dependency expressed through constructor argument with index 0 of type
[com.liferay.portal.model.User]: Ambiguous factory method argument
types - did you specify the correct bean references as factory method
arguments?
评论说您可以这样做,但如果您在该bean的xml定义中指定构造函数参数,则会失败。为了调用工厂方法,Spring需要访问用户实例以传递给createInstance。在本例中,我只是创建一个bean并将其传入:
<bean id="user" class="something.something.User">
</bean>
<bean id="validator" class="cz.instance.transl.validation.file.FileValidator" factory-method="createInstance">
<constructor-arg ref="user"/>
</bean>
上面写着:
args—使用静态工厂方法的显式参数创建原型时要使用的参数
因此bean定义必须是一个原型范围的bean,即
<bean id="fileValidator"
scope="prototype"
class="cz.instance.transl.validation.file.FileValidator"
factory-method="createInstance" />
您也可以使用抽象工厂来设置工厂bean属性。这里我们有一个创建动作的ActionFactory
<bean id="actions_factory" class="com.imagina.control.actions.impl.ActionFactoryImpl"/>
<bean id="load_person_action" class="com.imagina.control.actions.impl.LoadPersonAction"
factory-bean="actions_factory" factory-method="create">
<constructor-arg value="load_person_action"/>
</bean>
要使用此配置,您必须考虑以下几点:
阅读了20篇文章后,我发现如何让自定义工厂方法在运行时获取参数并不明显,特别是因为我们被迫使用构造函数arg标记,并将上下文中的现有bean引用为下面的设置,并且所讨论的类充当静态工厂方法
<bean id="user" class="something.something.User" />
<bean id="fileValidator"
class="cz.instance.transl.validation.file.FileValidator"
factory-method="createInstance" >
<constructor-args ref="user" />
</bean>
注意,这并不能解决使用context.getBean(arg1,arg2)的问题,因为该方法在该场景中不相关。之所以不是这样,是因为所有这些bean都是单例的,此时构造函数没有被调用。如果您在单用户系统中工作,这不是问题,也不需要关心任何事情,因为您的上下文中在任何时候都只有一个用户bean
但是,对于多用户系统,您需要确保每个真实用户都有一个唯一的用户bean,并且在工厂方法调用中使用了正确的用户bean
为了在多用户系统中实现这一点,您需要将bean类型更改为原型,并且您应该创建一个表示工厂的FileValidator bean(如果您计划将依赖项注入工厂),以及另一个表示新实例的bean FileValidator。它们都是相同的类类型,但必须为每个类指定唯一的名称。见下文:
<bean id="user" scope="prototype" class="something.something.User" />
<bean id="validatorFactory"
class="cz.instance.transl.validation.file.FileValidator">
<constructor-arg value="something" />
</bean>
<bean id="fileValidatorBean"
class="cz.instance.transl.validation.file.FileValidator"
scope="prototype"
factory-method="createInstance" >
<constructor-arg ref="user" />
</bean>
我说我需要在runtime-context.getBean(name,user)中传递参数。不幸的是,它的失败方式与原型相同。使用3.1.0。M2@lisak:首先,停止使用beta版本,坚持使用稳定版本(即3.0.x)它一定是3.1.0.M2中的一个bug。。。要找到原因是很复杂的,如果我找到了,我会设法提出一张罚单。谢谢你能解释一下为什么它一定是原型吗?我对spring还不熟悉。我已经尝试过你建议的方法,它对我非常有效。但我无法理解为什么我们需要同一个bean的两个引用(即validatorFactory和fileValidatorBean)。我试过使用单bean(即fileValidatorBean),但它不起作用。你能抽出点时间详细说明原因吗?请
<bean id="user" class="something.something.User" />
<bean id="fileValidator"
class="cz.instance.transl.validation.file.FileValidator"
factory-method="createInstance" >
<constructor-args ref="user" />
</bean>
public class X {
public void callFactoryAndGetNewInstance() {
User user = context.getBean("user");
user.setSomethingUsefull(...);
FileValidator validator = (FileValidator)context.getBean("fileValidator");
...
}
}
<bean id="user" scope="prototype" class="something.something.User" />
<bean id="validatorFactory"
class="cz.instance.transl.validation.file.FileValidator">
<constructor-arg value="something" />
</bean>
<bean id="fileValidatorBean"
class="cz.instance.transl.validation.file.FileValidator"
scope="prototype"
factory-method="createInstance" >
<constructor-arg ref="user" />
</bean>
public void someMethod() {
...
User user = context.getBean("user");
user.setSomethingUsefull(...);
FileValidator fileValidator =
(FileValidator)context.getBean("fileValidatorBean",
user);
...
}