tags:

views:

48

answers:

4

I am a user of class A, which is provided to me as a library. In my spring config I specify an A bean, which Spring happily instantiates for me. As a side effect, A creates its own instance of B, which it exposes via A.getB(). B exposes a setC() method that I wish to invoke with a C that I configure in spring. How do I do this?

I've looked at util:property-path to reference the B but that won't let me put any content inside of it. I also looked at proxying but there just seems to be no way to get a hold of B and do something to it while I am trapped within the declarative world.

Repeat, I cannot create B. It is created only as a side effect of the creation of A. There are no convenience methods on A allowing me to call A.setC().

Help?

A: 

Take a look at factory methods. They allow you to tell Spring to obtain B via another path than using a constructor (via A in your example).

Fried Hoeben
That says "instantiation using an instance factory method is where a non-static method of an existing bean from the container is invoked to create a new bean." That would work if the library provided an A.createB() method. But it does not. B is already created, as a side effect, and all I have available to me is A.getB().
Kevin Pauli
Does that really matter whether it is a new instance in this case, all Spring has to know it should call getB to obtain the objects? Have you tried: factory-method="getB"?
Fried Hoeben
Hmmm... good point
Kevin Pauli
+1  A: 

Spring does provide mechanisms to allow one Spring bean to act as the factory for another, but it's an approach that rapidly runs into difficult when you start chaining factories together - the declarative approach doesn't work too well there.

When you have non-trivial arrangements like you've described, it's generally easier to implement your own FactoryBean, which becomes responsible for instantiating your non-bean-friendly object graph. The FactoryBean is injected with all of the necessary collaborators, and then does the wiring up manually, giving you your desired imperative approach.

This pattern is generally used to configure legacy components that don't have IoC-friendly signatures, but it's just as useful for building whole graphs of interacting objects.

skaffman
A: 

You can use a FactoryBean

The scheme with FactoryBean is as follows:

  • define your bean with

    <bean id="myBean" class="myFactoryClass">
          <property name="c" ref="yourObjectToBeInjectedInC" />
    </bean>
    
  • create your factory class which implements FactoryBean.
  • define a property named c (with a setter/getter)
  • define a property of type A, called instance for examle.
  • in the afterPropertiesSet method, instantiate call this.a = new A();, and then a.getB().setC(this.c);
  • in the getObject() method (required by the BeanFactory interface) add return instance;
  • make isSingleton() return true (if you don't want it to be prototype, of course)
  • make getObjectClass() return A.class;

You can now freely inject myBean (of type A).

Bozho
A: 

Assuming that B gets instantiated when A is constructed, have you considered this?

<bean id="a" class="com.example.A">
 <property name="b.c" ref="c"/>
</bean>

<bean id="c" class="com.example.C" />
beny23
is this possible?
Bozho
I did a quick test before posting the answer, so yes.
beny23