注入运行时值的更好方法

时间:2012-02-29 10:03:39

标签: java spring dependency-injection

我是春季新手。我发现有时我们需要使用运行时数据构造一个对象,但是在Spring的构造函数注入中使用了固定值。我知道我可以创建一个setter方法并用它来改变它,但我不认为这是一个优雅的解决方案。谁能告诉我怎么做?

2 个答案:

答案 0 :(得分:3)

使用SpEL =>通过另一个豆

<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" )

使用SpEL =&gt;通过表达

如果可以使用任意表达式计算此参数:

<bean id="bet" class="UsDollars" scope="prototype">
   <constructor-arg value="#{ T(java.lang.Math).random() * 100.0 }"/>
</bean>

使用SpEL =&gt;通过系统属性

如果您的用例允许使用系统属性:

<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(...));