代码之家  ›  专栏  ›  技术社区  ›  tangens

如何修改Spring容器中定义的bean

  •  11
  • tangens  · 技术社区  · 15 年前

    我有两个定义SpringFramework(2.5.x版)bean的XML文件:

    containerBase.xml:
    <beans>
        <bean id="codebase" class="com.example.CodeBase">
            <property name="sourceCodeLocations">
                <list>
                    <value>src/handmade/productive</value>
                </list>
            </property>
        </bean>
    </beans>
    

    …和

    containerSpecial.xml:
    <beans>
        <import resource="containerBase.xml" />
    </beans>
    

    现在我想调整一下房子 sourceCodeLocations 蚕豆 codebase 在内部 containerSpecial.xml . 我需要再加一个值 src/generated/productive .

    一种简单的方法 是重写的定义 代码库 在里面 集装箱特殊.xml 加上两个值,一个来自 containerBase.xml 而新的:

    containerSpecial.xml:
    <beans>
        <import resource="containerBase.xml" />
    
        <bean id="codebase" class="com.example.CodeBase">
            <property name="sourceCodeLocations">
                <list>
                    <value>src/handmade/productive</value>
                    <value>src/generated/productive</value>
                </list>
            </property>
        </bean>
    </beans>
    

    有没有一种方法可以在不重新定义bean的情况下扩展列表?

    编辑2009-10-06:

    这样做的目的是拥有一个共享的标准容器 containerBase 它被许多不同的项目使用。每个项目都可以覆盖/扩展某些特定于该项目的属性。 containerSpecial . 如果项目不重写,则使用中定义的默认值。 集装箱基地 .

    5 回复  |  直到 7 年前
        1
  •  8
  •   Jason Gritman    15 年前

    你可以使用 BeanFactoryPostProcessor 在Spring容器实例化代码基bean之前更改bean的元数据。例如:

    public class CodebaseOverrider implements BeanFactoryPostProcessor {
    
        private List<String> sourceCodeLocations;
    
        public void postProcessBeanFactory(
                ConfigurableListableBeanFactory beanFactory) throws BeansException {        
            CodeBase codebase = (CodeBase)beanFactory.getBean("codebase");
            if (sourceCodeLocations != null)
            {
                codebase.setSourceCodeLocations(sourceCodeLocations);
            }
        }
    
        public void setSourceCodeLocations(List<String> sourceCodeLocations) {
            this.sourceCodeLocations = sourceCodeLocations;
        }
    
    }
    

    然后在contextspecial.xml中:

    <beans>
        <import resource="context1.xml" />
    
        <bean class="com.example.CodebaseOverrider">
            <property name="sourceCodeLocations">
                <list>
                    <value>src/handmade/productive</value>
                    <value>src/generated/productive</value>
                </list>
            </property>
        </bean>
    </beans>
    
        2
  •  3
  •   kdubb    15 年前

    对。bean定义可以具有引用父bean定义的“parent”属性。新的“子”定义继承了父级的大部分属性,这些属性中的任何一个都可以被重写。

    参见 Bean Definition Inheritance

    你也可以用 Collection Merging 从父bean定义和子bean定义合并列表属性定义。通过这种方式,您可以在父bean定义中指定一些列表项,并在子bean定义中向其添加更多项。

        3
  •  1
  •   jon077    15 年前

    是否有一种方法可以在手工前在属性或其他配置中定义列表?

    似乎应用程序的配置和连接是紧密耦合的。根据我的经验,如果在春天很难做点什么的话,很可能有另一种更简单的方法。

        4
  •  1
  •   Pascal Thivent    15 年前

    3种途径:

    1. 简单:有两个列表defaultsourcecodelocations和additionalsourcecodelocations,并让访问器方法检查这两个列表(或组合它们)。我在一些框架中看到了这一点-填充了一个默认的处理程序列表,然后添加了其他用户创建的处理程序列表…

    2. 更复杂但保持原始类干净:然后可以创建一个CodeBaseModifier类。这将有一个init方法来更改bean的注入实例。

      <bean id="codebaseModifier" class="com.example.CodeBase" init-method="populateCodeBase">
          <property name="sourceCodeLocations" ref="codebase"/>
          <property name="additionalSourceCodeLocations">
          <list>
              <value>src/handmade/productive</value>
          </list>
          </property>
      </bean>
      

    如果你想让它真正通用,你可以做一个bean修饰符,通过反射来实现这一点。如果使用这种方法,请小心订购。codebase的依赖bean必须确保首先实例化这个类(with depends-depends-on)

    3对2的变化…与其直接创建代码类,不如创建一个返回填充bean的工厂。这个工厂可以用类似于2的方式配置弹簧。具有默认的源代码位置和其他源代码位置

    除非您需要很多可扩展属性,否则我将使用选项1。

        5
  •  1
  •   Thrawn    13 年前

    在Spring3.0中,可以在“list”标签上指定merge=“true”。见 http://forum.springsource.org/archive/index.php/t-97501.html 详情。