【问题标题】:setting a property in a spring bean outside the spring bean definintion在 spring bean 定义之外的 spring bean 中设置属性
【发布时间】:2009-12-30 07:59:55
【问题描述】:

我在我的控制之外定义了一个 spring bean。我想在那个 spring bean 中设置一个属性,这可能来自 spring XML 吗?

例如 a.xml(不受我控制):

<bean id="a" class="A"/>
<bean id="b" class="B">
    <constructor-arg ref="a"/>
</bean>

b.xml(由我控制)

<import resource="classpath:META-INF/a.xml"/>
<bean id="c" class="C"/>
<!-- here i want to set a property in bean a -->

一个选项,但我不喜欢以编程方式设置属性。 我在java中使用spring 2.5。

【问题讨论】:

    标签: spring


    【解决方案1】:

    您可以将bean-a 注入另一个类并在那里设置它的属性

    <bean id="foo" class="...MySetterClass" init-method="init">
        <property name="candidateBean" ref="a"/>
        <property name="candidateProperty" value="bar"/>
    </bean>
    

    所以你的班级 MySetterClass 可以做类似的事情

    class MySetterClass {
        /*... Setter boilerplate */
        public void init(){
            candidateBean.setCandidateProperty(candidateProperty);
        }
    }
    

    这是一个非常丑陋的方法,但它应该可以工作。

    【讨论】:

    • 这就是我以编程方式进行的意思。我同意这很丑:-)
    • 应该可以,但有更好的解决方案!不要那样做
    【解决方案2】:

    你可以在spring配置中定义属性。

    <bean id="myBean"class="myClass">
      <property name="myProperty">
      </property>
    </bean>
    

    带有same name can be configured 的bean 和最后一个bean 将获胜(也许第一个我不太确定)。如果您以将定义作为最后一个加载的方式订购配置 xml 文件,它将重新定义 bean。

    【讨论】:

    • 也许这是可能的,但是 bean 被注入到同一个 spring 文件中的其他 bean 中,这些引用将指向“错误”的 bean。
    • 然后尝试在您的 xml 顶部定义它。
    • 尝试在导入之前(或之后)在 b.xml 中重新定义&lt;bean id="a" class="A"/&gt;。必须工作:forum.springsource.org/archive/index.php/t-25878.html
    【解决方案3】:

    不知道更多:

    您可以使提供的 bean 成为另一个 bean 的父级,并将属性值注入第二个 bean。然后,使用您创建的 bean 而不是提供的。

    <bean id="myNewBean" parent="suppliedBean">
        <property key="prop" value="foo"/>
    </bean>
    

    如果有其他 bean 引用了第一个 bean 需要具有您注入的属性值,或者有代码按名称查找此 bean,那么这将不起作用。同样,根据您的事务和 aop 配置,在某些情况下这不是您想要的。但是,如果您需要做的只是为您自己的代码在一个普通的旧 bean 上注入一个属性,这应该没问题。

    【讨论】:

    • 正如你所描述的,我遇到了其他 bean 将使用其他实例的问题......
    【解决方案4】:

    导入a.xml时:

    <bean id="a" class="A"/>
    <bean id="b" class="B">
        <constructor-arg ref="a"/>
    </bean>
    

    这对于客户端类上的 init 方法来修改 bean a 来说是丑陋的。

    我并没有真正理解这里的问题:某些框架可能为您提供了一个已经准备好、可以运行的 spring 上下文。如果你不喜欢这些已经准备好的东西,你为什么要在运行时用花哨的策略来修改它?这只是一个上下文。

    您可以在该上下文中重用您想要的 bean,如果您不喜欢 bean a,只需声明您自己的 bean a2

    仅当 bean a 用于您导入的上下文的许多 bean 时才会出现问题。 如果是这种情况,那么您可以复制 a.xml 上下文并对其进行自定义。


    如果你使用命名空间是因为它更容易,有时你会发现在使用命名空间时某些选项是不可能的,最后你还是选择使用 FactoryBean 或手动声明 bean。导入外部 xml 上下文时也是一样的:有时它不会做你想做的事。

    Spring 帮助您将对象连接在一起。命名空间或外部上下文是预定义的连接。如果您不喜欢预定义的接线,只需使用您自己的 xml 或 FactoryBean 自行完成。


    如果复制和自定义的连接非常大(多个 xml 文件等),并且您只想对单个 bean 执行一些修改,那么您应该尝试一下 Thomas Jung 告诉您的内容:覆盖你不喜欢的bean。有用! Spring's overriding bean

    【讨论】:

    • 这有点晚了,代码在生产中已经有好几年了 :-) 为了回应你写的东西,我需要修改那个实例,而不是一个新实例。此外,复制所有 XML 对更新不是很友好(因为第 3 方依赖项可能在某些时候需要更新),也不是使用覆盖 bean 的解决方案。我仍然认为没有完美的解决方案,但感谢您尝试改进答案。
    • 那么最好的解决方案可能是向您的第三方库开一张票,并告诉他们提供一个工厂 bean,其中包括一个可插入的策略来自定义 bean 创建,就像在 Spring 中完成的那样
    • 或者您可以使用 BeanPostProcessor,它只会在创建后仅修改类型 A(或具有“a”名称)的 bean。但它不应该是修改上下文本身的上下文的客户端:) 我知道我迟到了,只是想发表我的意见,以防有人读到它。
    • BeanPostProcessor 可能是一个可行的解决方案,我会在类似的问题中考虑这一点。是的,我同意第 3 方设计错误。实际上,它不是正在编辑的上下文,而是加载到上下文中的类的默认行为。
    猜你喜欢
    • 1970-01-01
    • 2012-08-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-11-24
    • 1970-01-01
    • 2022-08-20
    • 1970-01-01
    相关资源
    最近更新 更多