Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get beans created by FactoryBean spring managed?

The FactoryBean can be used to programmatically create objects which might require complex instantiation logic.

However, it seems that the beans created by the FactoryBean doesn't become spring managed. Is this interpretation correct? If so, are there any nice workarounds? A short code sample is included to illustrate my problem.

ApplicationContext:

<bean id="searcher" class="some.package.SearcherFactory" />  <bean id="service" class="some.package.Service" />  

Factory implementation:

public class SearcherFactory implements FactoryBean<Searcher> {      @Override     public Searcher getObject() throws Exception {         return new Searcher(); // not so complex after all ;)     }      @Override     public Class<Searcher> getObjectType() {         return Searcher.class;     }     ....  } 

Class created by the factory:

public class Searcher() {       private Service service;        @Autowired       public void setService(Service service) {            // never invoked            this.service=service;       }  } 
like image 919
Johan Sjöberg Avatar asked Feb 11 '11 14:02

Johan Sjöberg


People also ask

How do you get beans from Spring containers?

getBean() method. Simply put, as the name of the method also suggests, this is responsible for retrieving a bean instance from the Spring container.

How many instances are created for a Spring managed bean?

Singleton: Only one instance will be created for a single bean definition per Spring IoC container and the same object will be shared for each request made for that bean.


2 Answers

Here is an abstract FactoryBean implementation that does autowiring for you:

public abstract class AbstractAutowiringFactoryBean<T> extends     AbstractFactoryBean<T> implements ApplicationContextAware{      private ApplicationContext applicationContext;      @Override     public void setApplicationContext(         final ApplicationContext applicationContext){         this.applicationContext = applicationContext;     }      @Override     protected final T createInstance() throws Exception{         final T instance = doCreateInstance();         if(instance != null){             applicationContext               .getAutowireCapableBeanFactory()               .autowireBean(instance);         }         return instance;     }      /**      * Create the bean instance.      *       * @see #createInstance()      */     protected abstract T doCreateInstance();  } 

Extend it, implement the getObjectType() and doCreateInstance() methods and you're up and running with autowiring.

Note: BeanPostProcessors are not applied, that would require additional code.

like image 125
Sean Patrick Floyd Avatar answered Oct 11 '22 11:10

Sean Patrick Floyd


The object created by the FactoryBean are managed by Spring, but not instantiated or configured by Spring. By using a FactoryBean, you take responsibility for that yourself. All injection and config must be handled by the FactoryBean

There is an alternative which may work better for you - use annotation-based config instead of XML-based config. This means you can have complex instantiation logic in Java, whilst still using things like @Autowired on the objects themselves.

I tend to use annotation-style config for all non-trivial Spring apps now, it makes many things a lot easier.

like image 23
skaffman Avatar answered Oct 11 '22 10:10

skaffman