Spring并在运行时将参数传递给factory-method
方法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?
private FileValidator(User user) { this.user = user; } public static FileValidator createInstance(User user) { return new FileValidator(user); }
评论说你可以这样做,但如果你在该bean的xml定义中指定构造函数参数,它就会失败。
javadoc说:
args – 使用静态工厂方法的显式参数创建原型时使用的参数。
所以bean定义必须是原型范围的bean,即
阅读20篇文章,我发现如何获得自定义工厂方法在运行时获取参数并不明显,特别是因为我们被迫使用构造函数-arg标记并在上下文中引用现有bean作为设置下面和有问题的类充当静态工厂方法。
我通过从上下文中获取构造函数-arg中使用的bean实例,然后使用您在运行时使用的值填充它来实现它。 当您获得工厂生成的bean时,此bean将用作参数。
public class X { public void callFactoryAndGetNewInstance() { User user = context.getBean("user"); user.setSomethingUsefull(...); FileValidator validator = (FileValidator)context.getBean("fileValidator"); ... } }
请注意,这并不能解决使用context.getBean(arg1,arg2)时遇到的问题,因为该方法与此方案无关。 它不是因为所有这些bean都是单例,并且此时不调用构造函数。 如果您在单用户系统中工作,这不是问题,也不需要关心,因为无论如何您在上下文中只有1个用户bean!
但是,对于多用户系统,您需要确保每个真实用户都有一个唯一的User bean,并且您在工厂方法调用中使用了正确的User bean。
为了在多用户系统中执行此操作,您需要将bean类型更改为原型,并且您应该创建一个表示工厂的FileValidator的bean(如果您计划将dependency injection工厂)和另一个bean FileValidator代表您的新实例。 它们都属于同一类类型,但您必须为每个类别指定一个唯一的名称。 见下文:
在您希望从工厂获取此新FileValidator bean的类中,您可以使用以下技术:
public void someMethod() { ... User user = context.getBean("user"); user.setSomethingUsefull(...); FileValidator fileValidator = (FileValidator)context.getBean("fileValidatorBean", user); ... }
为了调用工厂方法,Spring需要访问用户实例以传递给createInstance。 在这种情况下,我只是创建一个bean并将其传入:
您也可以使用抽象工厂设置factory-bean属性。 这里我们有一个ActionFactory来创建动作。
要使用此配置,您必须考虑以下几点:
- create方法不是静态的。 现在属于一个实例
- constructor-arg是工厂方法的参数