Java – spring – constructor injects and overrides the parent definition of nested beans

I read the resources for spring 3 in inheriting bean definitions, but I'm confused about what's possible and impossible

For example, a bean that uses a collaborator bean configured with a value of 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>

Then, I want to be able to create similar beans with slightly different configured collaborators What can I do

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

I don't know it's possible. If so, it feels a little clumsy Is there a better way to cover a small part of a large nested bean definition? It seems that children already know a lot for their parents, such as constructor index

This is a toy example – in practice, a service is a large bean definition that depends on many other collaborator beans, including other bean dependencies For example, create a handler chain, and each bean references the next one in the chain I want to create an almost identical chain. There are some small changes in the middle handler. What should I do?

I don't want to change the structure - the service bean uses collaborators to perform its functions, but if it helps, I can add properties and use property injection

This is a duplicate pattern. Will you create a custom pattern help?

Thanks for any suggestions!

Editor: the conclusion of my question is that if I have a very large bean definition and create a complex bean (beans have beans, etc.), I want to create a few changes of almost the same bean, what should I do? Note that if your solution must use properties, or you can use constructor injection

Nesting and top-level beans are not a problem (in fact, I think all beans are top-level in practice)

Edit2: Thank you for your reply A factorybean may be an answer because it will reduce the complexity of the spring context and allow me to specify only differences as factory parameters However, it is not correct to reprogram a lot of context into code I've heard that scripts can be used in spring, such as groovy - does it provide another option? Can factories be created in groovy?

Solution

I'm not quite sure what you want to achieve I don't think you need to create your own custom schema (which is unusual for nested structures), but the following example may be very close and don't have to

First, define an abstract bean as the template for external beans (my example uses a car as the external bean and an engine as the internal bean), and give the default values that all other beans can inherit:

<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>

Since all Honda Civic have the same engine (I don't know anything about cars in my world), I give it a default nested engine bean Unfortunately, a bean cannot reference an abstract bean, so the default engine cannot be abstract I defined a specific bean for the engine, but marked it as lazy init, so it will not be instantiated unless another bean uses it:

<bean id="defaultEngine" class="Engine" lazy-init="true">
    <property name="numberOfCylinders" value="4"/>
    <property name="volume" value="400"/>
    <property name="weight" value="475"/>
</bean>

Now I can define my specific car and get all default values by referring to the bean defined by the parent:

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

My wife has a car like mine, except for a different model of it (again, I don't know about cars - let's assume that the engines are the same, even if they may not be in real life) Instead of redefining a bunch of beans / attributes, I just extend the default car definition again, but overwrite one of its attributes:

<bean id="myWifesCar" parent="defaultCar">
    <property name="model" value="Odyssey"/>
</bean>

My sister and my wife have the same car (really), but it has different colors I can extend a specific bean and override one or more properties on it:

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

If I like racing minivans, I might consider using a larger engine Here I extend a minivan and overwrite its default engine with a new engine This new engine extends the default engine and overrides some properties:

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

You can also do this more concisely using nested properties:

<bean id="supedUpMiniVan" parent="myWifesCar">
    <property name="engine.volume" value="600"/>
    <property name="engine.weight" value="750"/>
</bean>

This will use "defaultengine" However, if you create two vehicles in this way, each with different attribute values, the behavior will be incorrect This is because the two cars will share the same engine instance, and the second car overrides the property settings set on the first car This can be remedied by marking defaultengine as "prototype", and a new engine will be instantiated each time:

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

I think this example gives the basic idea If your data structure is complex, you can define multiple Abstract beans or create several different abstract hierarchies, especially if your bean hierarchy is deeper than two beans

Sidenote: my example uses attributes, which I believe is more clearly understood in spring XML and Java code However, the exact same techniques apply to constructors, factory methods, etc

The content of this article comes from the network collection of netizens. It is used as a learning reference. The copyright belongs to the original author.
THE END
分享
二维码
< <上一篇
下一篇>>