【发布时间】:2012-02-29 10:03:38
【问题描述】:
我是春季新手。我发现有时我们需要使用运行时数据来构造一个对象,但是在 Spring 的构造函数注入中使用了固定值。我知道我可以创建一个 setter 方法并用它更改值,但我认为这不是一个优雅的解决方案。谁能告诉我怎么做?
【问题讨论】:
-
示例、代码 sn-ps、cookie、现金等可能会有所帮助。
标签: java spring dependency-injection
我是春季新手。我发现有时我们需要使用运行时数据来构造一个对象,但是在 Spring 的构造函数注入中使用了固定值。我知道我可以创建一个 setter 方法并用它更改值,但我认为这不是一个优雅的解决方案。谁能告诉我怎么做?
【问题讨论】:
标签: java spring dependency-injection
<bean id="bank" class="UsBank">
<property name="moneyLeft" value="100"/> <!-- initial value -->
</bean>
<bean id="bet" class="UsDollars" scope="prototype">
<constructor-arg value="#{ bank.moneyLeft }"/>
</bean>
假设bank bean 被注入某处,因此您可以访问它:
bank.setMoneyLeft( 100 )
Bet currentBet = appContext.getBean( "bet" )
如果这个参数可以用任意表达式计算:
<bean id="bet" class="UsDollars" scope="prototype">
<constructor-arg value="#{ T(java.lang.Math).random() * 100.0 }"/>
</bean>
如果您的用例允许使用系统属性:
<bean id="bet" class="UsDollars" scope="prototype">
<constructor-arg value="#{ systemProperties['moneyLeft'] }"/>
</bean>
获取 bean:
System.setProperty( "moneyLeft", "5000" )
Bet currentBet = appContext.getBean( "bet" )
您可以阅读有关SpEL 的更多信息。
制作bet bean prototype => 需要注意的一点,如果注入到另一个bean中,它(另一个bean)也需要是原型,或者有一些AOP魔法可以使用,但在您的情况下可能并不那么重要。
如果上述 bean 不必是 prototype(这意味着您只需要此 bean 的一个实例,但在应用程序上下文创建时不是),您可以删除 scope="prototype" 并添加 lazy="true"。这将告诉 Spring 仅在首次引用该 bean 时尝试创建它。
【讨论】:
一般来说,我的偏好是像这样建造一个工厂:
@Service
public class RuntimeObjectFactoryImpl implements RuntimeObjectFactory {
private final CustomObjectTypeA oA;
private final CustomObjectTypeB oB;
@Autowired
public RuntimeObjectFactoryImpl(final CustomObjectTypeA oA, final CustomObjectTypeB oB) {
this.oA = oA;
this.oB = oB;
}
@Override
public RuntimeObject get(CustomObjectTypeC oC) {
return new RuntimeObject(oA, oB, oC);
}
}
这也可以在 XML 中进行配置(我通常建议在连接业务服务时使用注释而不是注释,但在这里使用注释是一个更形象的答案)。那么在运行时:
RuntimeObject o = runtimeObjectFactory.get(new CustomObjectTypeC(...));
【讨论】: