12

Short question: If I have class that impelemnts FactoryBean interface, how can I get from FactoryBean object itself instead of FactoryBean.getObject()?

Long question: I have to use 3-rd party Spring based library which is hardly use FactoryBean interface. Right now I always must configure 2 beans:

<!-- Case 1-->
<bean id="XYZ" class="FactoryBean1" scope="prototype">
    <property name="steps">
        <bean class="FactoryBean2">
            <property name="itemReader" ref="aName"/>
        </bean>
    </property>
</bean>

<bean id="aName" class="com.package.ClassName1" scope="prototype">
    <property name="objectContext">
        <bean class="com.package.ABC"/>
    </property>
</bean>

<!-- Case 2-->
<bean id="XYZ2" class="FactoryBean1" scope="prototype">
    <property name="steps">
        <bean class="FactoryBean2">
            <property name="itemReader" ref="aName2"/>
        </bean>
    </property>
</bean>

<bean id="aName2" class="com.package.ClassName1" scope="prototype">
    <property name="objectContext">
        <bean class="com.package.QWE"/>
    </property>
</bean>

Actyually defintion of a bean with name "XYZ" (compare with "XYZ2") never will be changed, but because of factory nature I must copy the code for each configuration. Definition of a bean with name "aName" always will be new (i.e. each configuration will have own objectContext value).

I would like to simplify the configuration have a single factory bean (remove "XYZ2" and rid of link to "aName"):

<bean id="XYZ" class="FactoryBean1" scope="prototype">
    <property name="steps">
        <bean class="FactoryBean2"/>
    </property>
</bean>

<bean id="aName" class="com.package.ClassName1" scope="prototype">
    <property name="objectContext">
        <bean class="com.package.ABC"/>
    </property>
</bean>


<bean id="aName2" class="com.package.ClassName1" scope="prototype">
    <property name="objectContext">
        <bean class="com.package.QWE"/>
    </property>
</bean>

Unfortunately, it's not as simple as I expect. I suppose to glue factory (i.e. XYZ bean from the example) with necessary objects (i.e. "aName", "aName2") at runtime. The approach doesn't work because when I ask Spring for FactoryBean object it returns to me FactoryBean.getObject() which impossible to instanciate at that time because of missing itemReader value.

I hope that SpringSource foresee my case I can somehome "hook" FactoryBean.getObject() call to provide all necessary properties at runtime.

Another complexity that disturb me a bit it's chains of Factories (Factory1 get an object from Factory2 that I have to "hook" at runtime).

Any ideas will be appreciated.

FoxyBOA
  • 5,788
  • 8
  • 48
  • 82

2 Answers2

20

It's the & (ampersand), not the At-symbol, see Spring Framework documentation: Customizing instantiation logic using FactoryBeans

<property name="factoryBean" ref="&amp;theFactoryBean" />
reevesy
  • 3,452
  • 1
  • 26
  • 23
mhaller
  • 14,122
  • 1
  • 42
  • 61
  • 1
    Did you really check it? I've tried this way and it fails with exception like: Caused by: org.xml.sax.SAXParseException: The reference to entity "theFactoryBean" must end with the ';' delimiter. – wax Aug 09 '10 at 14:59
  • @wax: thanks, of course you are right, the XML must be escaped properly. I've corrected it – mhaller Aug 12 '10 at 14:42
  • Just don't try this inside an EL expression. I have a bug in for it :) #{&theFactoryBean} does not work :( – Matt Aug 20 '12 at 13:14
2

You can get the factory bean itself using the & syntax in the spring config:

<property name="factoryBean" ref="&theFactoryBean" />

as opposed to:

<property name="createdBean" ref="theFactoryBean" />
oxbow_lakes
  • 133,303
  • 56
  • 317
  • 449