Spring配置将属性传递给引用的bean

时间:2014-02-21 10:55:07

标签: java spring java-ee javabeans

我有以下设置:

<bean id="b1" class="SomeClass">
    <property name="foo" ref="foo1"/>
</bean>

<bean id="b2" class="SomeClass">
    <property name="foo" ref="foo2"/>
</bean>

<bean id="foo1" class="FooClass">
    <constructor-arg index="0"><ref bean="dataSource1"/></constructor-arg>
    ...other constructor args
</bean>

<bean id="foo2" class="FooClass">
    <constructor-arg index="0"><ref bean="dataSource2"/></constructor-arg>
    ...other constructor args
</bean>

有没有办法可以避免重复FooClass?我想在bean b1和b2中做的是添加对FooClass的引用,但指定数据源所有其他构造函数参数都是相同的。

由于

吉姆

4 个答案:

答案 0 :(得分:1)

如果您希望在每次调用相应的getter时动态初始化/填充您的类的某个成员,您可以尝试查找方法注入。阅读第3.3.4.1页here

因此,即使每次访问分配了查找方法的字段时,包含动态成员的类都是在scope = singletone(spring bean容器的缺省值)中创建的,您将获得一个适当的对象。在查找方法中实现的业务逻辑。

另外,我在Spring文档中发现了一个很好的example - 我认为非常清楚。看看“3.4.6.1查找方法注入”

答案 1 :(得分:1)

你在这里做的是,使用constructure自动装配类,如aviad所说,你可以使用setter和getter方法进行数据源注入

<bean id="foo" class="FooClass">
    <constructor-arg index="0">datasource</constructor-arg>
    ...other constructor args
</bean>

   <bean>your datasource bean1</bean>
   <bean>your datasource bean2</bean>

在您的实施中,您可以将数据源设置如下

@Autowire
private FooClass foo;

foo.setDataSource(datasourcebean1);

你fooClass

public void FooClass(Datasource datasource){

      private Datasource datasource;

      public void setDatSource(Datasource datasource);

      public Datasource  getDataSource();
}

编辑 - 根据spring文档,如果它的值没有变化,你可以传递构造函数参数。但是对于FooClass,你希望在不同的场合传递不同的数据源(希望我能正确理解),所以在这种情况下你需要在spring初始化期间传递datasouce实例数据源1或数据源2,因为spring会期望构造函数参数在初始化FooClass时。稍后在运行时传递不同的数据源并使用setter方法设置数据源。

bean spring config

  <bean id="foo" class="FooClass">
        <constructor-arg index="0" ref="datasource1"></constructor-arg>
        ...other constructor args
    </bean>

public class FooClass(){
      // on spring initialization, it will inject datasource1 
      public void FooClass(DataSource dataSource){
      }
      have your setter and getter method for datasource
}

您的通话服务中的位置

public class dataBaseInvoke(){

public Datasource datasource2

public FooClass fooClass;

inside method{
   fooClass.setDatasource(datasource2);
   fooClass.addFoo();
}
}

答案 2 :(得分:0)

使用抽象bean

<bean id="foo" class="FooClass">
  // Set all properties except datasoure
  <property name="..." />
</bean>

<bean id="foo1" parent="foo">
  <property name="datasource" ref="ds1" />
</bean>
<bean id="foo2" parent="foo">
  <property name="datasource" ref="ds2" />
</bean>

当然,您必须使用空的构造函数实例化,并使用访问器公开FooClass属性。如果您在其他地方不需要foo1foo2,请选择内部bean。

答案 3 :(得分:0)

考虑到您的实现,您可能希望选择 Bean定义继承

从春天documentation

  

bean定义可以包含很多配置信息,   包括构造函数参数,属性值和   容器特定的信息,如初始化方法,静态   工厂方法名称,等等。子bean定义继承   来自父定义的配置数据。孩子的定义可以   根据需要覆盖某些值或添加其他值。使用父母和孩子   bean定义可以节省大量的输入。实际上,这是一种形式   模板化。

基本上它说的是你可以有一种“Bean定义的模板”将其标记为抽象,并在其他兼容的bean中使用它作为 parent 来继承这些配置。

此样本取自春季documentation

<bean id="inheritedTestBean" abstract="true"
      class="org.springframework.beans.TestBean">
  <property name="name" value="parent"/>
  <property name="age" value="1"/>
</bean>

所以此时此bean未实例化,仅用于bean定义继承。

<bean id="inheritsWithDifferentClass"
      class="org.springframework.beans.DerivedTestBean"
      parent="inheritedTestBean" init-method="initialize">

  <property name="name" value="override"/>
  <!-- the age property value of 1 will be inherited from  parent -->

</bean>

在这里你可以看到org.springframework.beans.DerivedTestBean用于实例化bean,但它将使用父的所有定义,而且,它将覆盖属性name。不需要在父项上指定类,但如果在父项(inheritedTestBean)上指定而不在子项(inheritsWithDifferentClass)上指定,则将使用父类来实例化子项。并非所有内容都是继承的,我们可以在这里看到:

  

子bean定义继承构造函数参数值property   值和来自父级的方法覆盖,以及要添加的选项   新的价值观。任何初始化方法,destroy方法和/或静态   您指定的工厂方法设置将覆盖   相应的父设置。

     

其余设置始终取自子定义:   取决于,autowire模式,依赖性检查,单例,范围,懒惰   初始化。

以下是使用您的课程的示例:

<!-- the way you are already using it -->
<bean id="b1" class="SomeClass">
  <property name="foo" ref="foo1"/>
</bean>

<!-- if you use it just once, you could declare it inside the bean that uses it -->    
<bean id="b2" class="SomeClass">
  <property name="foo">
    <bean id="foo1" class="FooClass" parent="foo">
      <constructor-arg index="0"><ref bean="dataSource1"/></constructor-arg>
    </bean>
  </property>
</bean>

<!-- here no class definition, only the default configuration -->
<bean id="foo" abstract="true">
  <!-- constructor arg 0 is defined only on child beans -->
  <constructor-arg index="1" value="whatever1" />
  <constructor-arg index="2" value="whatever2" />
  <constructor-arg index="3" value="whatever3" />
  <constructor-arg index="4" value="whatever4" />
</bean>

<bean id="foo2" class="FooClass">
  <constructor-arg index="0"><ref bean="dataSource2"/></constructor-arg>
</bean>