我是春季新手。我发现有时我们需要使用运行时数据构造一个对象,但是在Spring的构造函数注入中使用了固定值。我知道我可以创建一个setter方法并用它来改变它,但我不认为这是一个优雅的解决方案。谁能告诉我怎么做?
答案 0 :(得分:3)
<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 =&gt;的一件事需要注意如果它被注入另一个bean,它(另一个bean)也需要是一个原型,或者有一些可以使用的AOP魔法,但在你的情况下它可能不是那么重要。
如果上面的bean不一定是prototype
(这意味着你只需要这个bean的一个实例,但是在应用程序上下文创建时不),您可以删除scope="prototype"
并添加lazy="true"
。这将告诉Spring只在第一次引用时尝试创建它。
答案 1 :(得分:1)
一般来说,我的偏好是建造一个这样的工厂:
@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(...));