2014-02-21 112 views
2

我有以下设置:Spring配置通属性引用bean

<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中,但是指定数据源的所有其他构造函数参数都是相同的。

感谢

吉姆

+0

另一点,我当时无法使用注释配置必须是在XML –

回答

0

考虑到你的实现,你可能想要去寻找Bean Definition Inheritance

从春天documentation

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

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

这个样本是从春天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用于实例豆,但它会使用父母的所有定义,再加上,它会覆盖属性name。该类不需要在父级上指定,但是如果在父级(inheritedTestBean)而不是在子级(inheritsWithDifferentClass)上指定,父级将用于实例化子级。并非一切都被继承,因为我们可以在这里看到:

子bean定义继承构造器参数值,属性值 ,并从父类的方法覆盖,以增加 新值的选项。您指定的任何初始化方法,销毁方法和/或静态 工厂方法设置都将覆盖对应父级设置 。

其余设置始终取自子定义: 取决于,自动装配模式,依赖项检查,单例,范围,惰性 init。

下面是使用你的类的例子:

<!-- 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> 
+0

感谢弗朗西斯科,我已经使用了您建议的方法,我认为这是实现我想要的而不会有太多重复配置的最佳方式。 –

1

如果你希望你的类的一些成员进行动态初始化\居住在每次调用相应的getter,你可以尝试查找方法注入。阅读第3.3.4.1页here

因此,即使包含动态成员的类是在scope = singletone(spring bean容器的默认值)中创建的,每次访问具有指派的查找方法的字段时,都会根据在查找方法内部实现的业务逻辑。

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

+0

感谢您的答复。我认为这不会对我的情况有所帮助。从我可以看到的方法注入混合单身人士和原型豆。我所有的bean都是单例,我想要做的就是尽量避免为同一个类配置几乎相同的配置,当我需要的是使用不同的数据源时。如果我使用方法注入,我怎么知道哪个数据源返回? –

1

你在这里是做什么的,自动装配类建设浅析,为阿维亚德说,你可以使用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(); 
} 

EDIT-按照Spring文档,如果它的值没有改变,你可以传递构造函数参数。但是对于FooClass来说,你希望在不同的场合传递不同的数据源(希望我能正确得到它),所以在这种情况下,你需要在spring初始化时传递datasource实例或者datasource1或者datasource2,因为Spring会期望构造函数参数同时初始化FooClass。稍后在运行时传递不同的数据源并使用setter方法设置数据源。

豆Spring配置

<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(); 
} 
} 
+0

我不确定这是如何工作的。在你的例子中,你传递给FooClass构造函数的是什么?我以为你必须传递一个对数据源bean的引用。另外我无法使用@Autowire。 –

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在其他地方去内豆。