Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/323.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java spring构造函数注入和重写嵌套bean的父定义_Java_Spring - Fatal编程技术网

Java spring构造函数注入和重写嵌套bean的父定义

Java spring构造函数注入和重写嵌套bean的父定义,java,spring,Java,Spring,我已经阅读了关于Spring3的参考资料,但是我对什么是可能的和什么是不可能的感到困惑 例如,采用Collaboratorbean的bean,配置为值12 <bean name="beanService12" class="SomeSevice"> <constructor-arg index="0" ref="serviceCollaborator1"/> </bean> <bean name="serviceCollaborator1" c

我已经阅读了关于Spring3的参考资料,但是我对什么是可能的和什么是不可能的感到困惑

例如,采用Collaboratorbean的bean,配置为值12

<bean name="beanService12" class="SomeSevice">
    <constructor-arg index="0" ref="serviceCollaborator1"/>
</bean>

<bean name="serviceCollaborator1" class="SomeCollaborator">
    <constructor-arg index="0" value="12"/> 
    <!-- more cargs, more beans, more flavor -->
</bean>

然后,我希望能够创建类似的bean,配置的协作者略有不同。我能做点像这样的事吗

   <bean name="beanService13" parent="beanService12">
       <constructor-arg index="0">
          <bean>
             <constructor-arg index="0" value="13"/>
          </bean>
       </constructor>
   </bean>

我不确定这是否可能,如果可能的话,感觉有点笨重。有没有更好的方法覆盖大型嵌套bean定义的小部分?子bean似乎必须对父bean了解很多,例如构造函数索引

这是一个有趣的例子——实际上,服务是一个大型bean定义,依赖于许多其他协作bean,这些协作bean也具有其他bean依赖性。例如,创建了一个处理程序链,其中每个bean引用链中的下一个,该链引用下一个。我想创建一个几乎相同的链,中间有一些小的处理程序,怎么办? 我不想改变结构——服务bean使用协作者来执行其功能,但如果有帮助的话,我可以添加属性并使用属性注入

这是一个重复的模式,创建自定义模式会有帮助吗

谢谢你的建议

编辑:我的问题的核心是,如果我有一个非常大的bean定义,并且创建了一个复杂的bean层次结构(bean的属性是bean等),我想创建一个几乎相同的bean,只需做一些更改,我怎么做?请说明您的解决方案是否必须使用属性,或者是否可以使用构造函数注入

嵌套bean和顶级bean不是问题所在(事实上,我认为所有bean实际上都是顶级的。)


编辑2:谢谢你迄今为止的回答。FactoryBean可能是答案,因为这将降低spring上下文的复杂性,并允许我将差异指定为工厂的参数。但是,将一大块上下文推回到代码中感觉是不对的。我听说spring可以与脚本一起使用,例如groovy——这是否提供了一种替代方案?工厂是否可以在groovy中创建?

您的示例将无法按照指定的方式工作,因为嵌套bean定义没有指定
类或
父类。您需要添加更多信息,如下所示:

<bean name="beanService13" parent="beanService12">
   <constructor-arg index="0">
      <bean parent="beanBaseNested">
         <constructor-arg index="0" value="13"/>
      </bean>
   </constructor>

尽管我不确定用这样的名称引用嵌套bean是否有效

嵌套bean定义应谨慎对待;它们会很快升级为不可读性。考虑将内部bean定义为顶层bean,这将使外部bean定义更易于阅读。 至于需要知道父bean的构造函数索引的子bean,这是Java构造函数注入的一个更基本的问题,因为Java构造函数参数不能通过名称来引用,只能通过索引来引用。Setter注入几乎总是更具可读性,代价是失去构造函数注入的最终性


正如您所提到的,自定义模式始终是一个选项,尽管设置起来有点麻烦。如果你发现自己经常使用这种模式,那么这可能是值得努力的。

我不完全确定你想要实现什么。我认为,如果不创建自己的自定义模式(这对于嵌套结构来说是非常重要的),就无法完全实现您想要的,但是如果不这样做,下面的示例可能非常接近

首先,定义一个抽象bean作为外部bean的模板(我的示例使用汽车作为外部bean,使用引擎作为内部bean),为其提供所有其他bean都可以继承的默认值:

<bean id="defaultCar" class="Car" abstract="true">
    <property name="make" value="Honda"/>
    <property name="model" value="Civic"/>
    <property name="color" value="Green"/>
    <property name="numberOfWheels" value="4"/>
    <property name="engine" ref="defaultEngine"/>
</bean>
现在我可以定义我的特定汽车,通过引用bean获取所有默认值,在bean中通过
parent
定义它们:

<bean id="myCar" parent="defaultCar"/>

我妻子有一辆和我一样的车,只是型号不同(再说一遍,我对汽车一无所知——让我们假设发动机是一样的,即使在现实生活中它们可能不是)。我没有重新定义一堆bean/属性,而是再次扩展了默认的汽车定义,但覆盖了它的一个属性:

<bean id="myWifesCar" parent="defaultCar">
    <property name="model" value="Odyssey"/>
</bean>
<bean id="supedUpMiniVan" parent="myWifesCar">
    <property name="engine">
        <bean parent="defaultEngine">
            <property name="volume" value="600"/>
            <property name="weight" value="750"/>
        </bean>
    </property>
</bean>

我姐姐的车和我妻子的车(真的)是一样的,但颜色不同。我可以扩展一个具体的bean并覆盖其上的一个或多个属性:

<bean id="mySistersCar" parent="myWifesCar">
    <property name="color" value="Silver"/>
</bean>

如果我喜欢赛车小型车,我可能会考虑买一个更大的引擎。这里我扩展了一个Minivanbean,用一个新引擎覆盖它的默认引擎。此新引擎扩展了默认引擎,覆盖了以下几个属性:

<bean id="myWifesCar" parent="defaultCar">
    <property name="model" value="Odyssey"/>
</bean>
<bean id="supedUpMiniVan" parent="myWifesCar">
    <property name="engine">
        <bean parent="defaultEngine">
            <property name="volume" value="600"/>
            <property name="weight" value="750"/>
        </bean>
    </property>
</bean>

您还可以使用以下方法更简洁地执行此操作:


这将使用“defaultEngine”。但是,如果以这种方式创建两辆车,每辆车都具有不同的特性值,则该行为将不正确。这是因为两辆车将共享同一个引擎实例,第二辆车将覆盖第一辆车上设置的属性设置。这可以通过将defaultEngine标记为“原型”来解决,该原型在每次引用时都会实例化一个新的原型:

<bean id="defaultEngine" class="Engine" scope="prototype">
    <property name="numberOfCylinders" value="4"/>
    <property name="volume" value="400"/>
    <property name="weight" value="475"/>
</bean>

我认为这个例子给出了基本的想法。如果您的数据结构很复杂,您可以定义多个抽象bean,或者创建多个不同的抽象层次结构——特别是如果您的bean层次结构比两个bean更深的话


旁注:我的示例使用了属性,我认为在SpringXML和Java代码中,这些属性更容易理解。然而,完全相同的技术适用于构造函数、工厂方法等。

你想过用工厂来代替吗

您可以将bean配置为具有工厂,并且可以对不同的参数进行编码
<bean id="protoBean" scope="prototype">
 <property name="dependency1" ref="some bean" />
 <property name="dependency2" ref="some other bean" />
 ...
</bean>
public class PrototypeConsumingBean implements ApplicationContextAware {

 public void dynmicallyCreateService(String serviceParam) {
   // creates a new instance because scope="prototype"
   MyService newServiceInstance = (MyService)springContext.getBean("protoBean");
   newServiceInstance.setParam(serviceParam);
   newServiceInstance.mySetup();
   myServices.add(newServiceInstance);
 }

 public void setApplicationContext(ApplicationContext ctx) {
  m_springContext = ctx;
 }
}