鸡肉和鸡蛋春豆绑定

时间:2011-11-08 01:46:08

标签: java spring inversion-of-control

好的,这是我的用例:

我有以下类,每个类都封装了下一个实例。所以:

A - > B - > C - > d

例如:在A类中,我有一个B类实例,在B类中我有一个C实例,依此类推。

好吧,我正在尝试将loading \ initialization \ injection逻辑转换为混合Spring系统。一般的想法是B,C和D需要或多或少ApplicationContextAware。我的意思是,他们实际上不会实现该接口,而是需要ApplicationContext作为构造函数参数。这样,在混合方法中(开发人员不使用Spring来初始化实例),他们必须至少传递ApplicationContext,以便可以连接其他bean。问题是,为了让Spring容器加载bean,我现在必须传入XML中的ApplicationContext。但据我所知,没有好办法做到这一点。

我试过这样的事情:

public class ApplicationContextPlaceholder implements ApplicationContextAware {

    private ApplicationContext _applicationContext;

    public void setApplicationContext( final ApplicationContext applicationContext ) throws BeansException {
        _applicationContext = applicationContext;
    }

    public ApplicationContext getApplicationContext() {
        return _applicationContext;
    }

}

<bean id="a" class="com.company.A">
    <constructor-arg>
        <bean id="applicationContext" class="com.company.ApplicationContextPlaceholder" />
    </constructor-arg>
</bean>

但显然这没有任何意义,因为ApplicationContextPlaceholder不是真的ApplicationContext。我也在寻找在XML中引用上下文的方法,但我找不到任何东西。

有没有人知道这种问题的优雅解决方案?

编辑#1:

我正在思考它,我可以让ApplicationContextPlaceholder同时实现ApplicationContext并委托给注入的上下文,然后我想到也许,也许这可能已经在Spring中了。但据我所知,没有。

编辑#2:

每个类需要ApplicationContext的原因是,如果dev希望覆盖链中的一个类(例如,为了参数而使用C)。在这种情况下,C的子类仍然需要通过Spring加载D.

2 个答案:

答案 0 :(得分:1)

除非某个类提供额外的管道功能,否则应避免暴露ApplicationContext。引用Spring引用:in general you should avoid it, because it couples the code to Spring and does not follow the Inversion of Control style

如果您要提供其他功能(例如,可能是使用ApplicationContext组装对象的工厂类),那么实施ApplicationContextAware是谨慎的,因为您的功能已经与Spring绑定。

如果你已经考虑了dependency injection替代方案,并决定在你的bean中注入ApplicationContext,那么你的ApplicationContextPlaceholder类(我会远离Placeholder前缀避免与Spring property placeholders混淆是一种解决方案。 (由于它是您自己的类,为什么不扩展ApplicationObjectSupport以获得其他功能。)

需要在配置中定义和初始化此类,例如:

<bean id="appCtxHolder" class="ApplicationContextHolder" />

由于ApplicationContextHolder实现了ApplicationContextAware,因此Spring会在初始化时将ApplicationContext注入appCtxHolder。您可以将它用于构造函数注入,如:

<bean id="a" class="com.company.A">
    <constructor-arg>
        <bean factory-bean="appCtxHolder" factory-method="getApplicationContext" />
    </constructor-arg>
</bean>

答案 1 :(得分:0)

ApplicationContextPlaceholder可以让一切都变得静止。在这种情况下,您不需要传递ApplicationContext,当API请求某个bean时,您可以检查它是否为null,如果是,则使用来自{{ApplicationContext的{​​{1}}加载它。 1}}。这是假设基于setter的注入,如果你正在构建基于构造函数,你也可以在构造函数中初始化bean。