Spring 并在运行时将参数传递给工厂方法
方法 context.getBean(name, user) 的文档说
允许指定显式构造函数参数/工厂方法 论据
但无论我做什么(尝试了一切),使用最合乎逻辑的设置,当在初始化期间加载bean时,我得到这个:
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 id="fileValidator"
class="cz.instance.transl.validation.file.FileValidator"
factory-method="createInstance" />
private FileValidator(User user) {
this.user = user;
}
public static FileValidator createInstance(User user) {
return new FileValidator(user);
}
注释说你可以做到这一点,但如果你在该bean的xml定义中指定构造函数参数或不,它会失败。
The documentation of method context.getBean(name, user) says
Allows for specifying explicit constructor arguments / factory method
arguments
but no matter what I do (tried everything), with the most logical setting I get this when the beans are being loaded up during initialization:
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 id="fileValidator"
class="cz.instance.transl.validation.file.FileValidator"
factory-method="createInstance" />
private FileValidator(User user) {
this.user = user;
}
public static FileValidator createInstance(User user) {
return new FileValidator(user);
}
The commentary says you can do it, but if you specify constructor arguments in xml definiton of that bean or not, it fails.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
javadoc 说:
因此,bean 定义必须是原型范围的 bean,即
The javadoc says:
So the bean definition must be a prototype-scoped bean, i.e.
阅读了 20 篇文章,我发现如何让自定义工厂方法在运行时获取参数并不明显,特别是因为我们被迫使用 constructor-arg 标签并在上下文中引用现有的 bean 作为 setup下面以及所讨论的类充当静态工厂方法。
我通过从上下文中获取构造函数参数中使用的 bean 实例,然后用运行时使用的值填充它来使其工作。当您获取工厂生成的 bean 时,该 bean 将用作参数。
请注意,这并不能解决使用 context.getBean(arg1, arg2) 所要求的问题,因为该方法在此场景中不相关。之所以不是,是因为所有这些 bean 都是单例的,此时构造函数未被调用。如果您在单用户系统中工作,这不是问题,也没有什么需要关心的,因为无论如何,您的上下文中在任何时候都只有 1 个 User bean!
然而,对于多用户系统,您需要确保每个真实用户都有一个唯一的 User bean,并且在工厂方法调用中使用正确的 User bean。
为了在多用户系统中执行此操作,您需要将 bean 类型更改为原型,并且您应该创建代表工厂的 FileValidator 的 bean(如果您计划将依赖项注入到工厂中)和另一个 bean代表您的新实例的 FileValidator。它们都属于相同的类类型,但您必须为每个类指定一个唯一的名称。参见下文:
在您想要从工厂获取这个新 FileValidator bean 的类中,您可以使用以下技术:
Reading across 20 posts, I found that it was not apparent how to get a custom factory method to take parameters at run-time, especially since we are forced to use the constructor-arg tags and refer to an existing bean in the context as setup below and the class in question acting as a static factory method.
I got it working by fetching an instance of the bean used in the constructor-arg out of the context and then populating it with the values that you are working with at run-time. This bean will then be used as the parameter when you get your factory-generated bean.
Note this doesn't solve the problem asked of using context.getBean(arg1, arg2) as that method isn't relevant in this scenario. The reason it isn't is because all these beans are singleton and at this point the constructor isn't invoked. Not a problem and not anything to care about if you are working in a single-user system as you only have 1 User bean in your context at any time anyhow!
However, For a multi-user system you will need to make sure that you have a unique User bean for each real user and that you use the correct User bean in the factory method invocation.
In order to do this in a multi-user system, you will need to change the bean types to be prototype AND you should create a bean of your FileValidator that represents the factory (if you plan to dependency injection into the factory) and another bean FileValidator that represents your new instance. They will both be of the same class type but you must give each one a unique name. See below:
and in the class where you would like to get this new FileValidator bean from the factory, you can use the technique below:
为了调用工厂方法,Spring 需要访问用户实例以传递给 createInstance。在本例中,我只是创建一个 bean 并将其传递进去:
In order to call your factory method Spring needs access to a user instance to pass to createInstance. In this case I am just creating a bean and passing it in:
您也可以使用抽象工厂来设置factory-bean 属性。这里我们有一个创建动作的 ActionFactory。
要使用此配置,您必须考虑以下几点:
You can use an abstract factory too setting the factory-bean attribute. Here we have an ActionFactory which create actions.
To use this configuration you have to take this points in account: