Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to inject FactoryBean instead of object it produces?

Tags:

java

spring

Let's say I have following Spring config (version of Spring is 3.0.3):

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation="http://www.springframework.org/schema/beans
   http://www.springframework.org/schema/beans/spring-beans.xsd">

   <bean id="theFactoryBean" class="wax.MyFactoryBean"/>

   <bean id="factoryBeanUser" class="wax.FactoryBeanUser">
       <!-- what should be placed here?-->
   </bean>

</beans>

I have instance of FactoryBean implementation and some other instance. I need Spring to inject to other instance FactoryBean, not the object it produces.

There are two possible ways to solve it.

First one, obvious and malfunctional:

 <bean id="factoryBeanUser" class="wax.FactoryBeanUser">
    <property name="myFactoryBean" ref="&theFactoryBean"/>
</bean>

With this config Spring throws following exception on start:

    [skipped irrelevant part]
Caused by: org.xml.sax.SAXParseException: The reference to entity "theFactoryBean" must end with the ';' delimiter.
at com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.createSAXParseException(ErrorHandlerWrapper.java:195)
at com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.fatalError(ErrorHandlerWrapper.java:174)
at com.sun.org.apache.xerces.internal.impl.XMLErrorReporter.reportError(XMLErrorReporter.java:388)
at com.sun.org.apache.xerces.internal.impl.XMLScanner.reportFatalError(XMLScanner.java:1414)

I found this solution Spring: Getting FactoryBean object instead of FactoryBean.getObject(), this question is maked as answered and four people voted for it. So I assume that this solution might work, but currently there is something wrong in my code.

Second one, working but awkward:

public class FactoryBeanUser implements ApplicationContextAware{

private MyFactoryBean myFactoryBean;

   public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        myFactoryBean = (MyFactoryBean)applicationContext.getBean("&theFactoryBean");
   }
}

My question is it possible to make first approach functional or I should stick with a second way?

like image 741
wax Avatar asked Aug 09 '10 15:08

wax


People also ask

Which of the following methods are provided by FactoryBean interface?

Let's discuss the three methods: getObject() – returns an object produced by the factory, and this is the object that will be used by Spring container. getObjectType() – returns the type of object that this FactoryBean produces. isSingleton() – denotes if the object produced by this FactoryBean is a singleton.

How do I make factory beans?

To create a factory bean, all you have to do is to implement the FactoryBean interface by your creator bean class which will be creating actual other beans. Or to keep it simple, you can extend AbstractFactoryBean class.

What is bean factory method?

Factory-method is used for calling a static method to create object in same bean class. Factory-bean is used for creating a object based on factory design pattern.

What is instance factory method instantiation?

3.3.2.3 Instantiation using an instance factory method Similar to instantiation through a static factory method, instantiation with an instance factory method invokes a non-static method of an existing bean from the container to create a new bean.


1 Answers

It seems the XML parser interprets the ampersand (&) as a start of an XML-entity. You can try using ref="&amp;theFactoryBean".

The spring docs is not clear whether this syntax is allowed in an xml file, or only with programatic lookup. But then the xml configuration is used by the app context, so I assume the &amp; should work (although it seems it has not been the best choice for a special symbol)

Here's why I'd suggest another thing - if you really need the factory bean rather than its product, create another bean, that does not implement FactoryBean, define a method createObject() or something like that, and use it in all factories that need it.

A sidenote - better reference the xsd with the version included:

http://www.springframework.org/schema/beans/spring-beans-3.0.xsd

like image 180
Bozho Avatar answered Oct 16 '22 03:10

Bozho