Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

FactoryBeans and the annotation-based configuration in Spring 3.0

Tags:

Spring provides the FactoryBean interface to allow non-trivial initialisation of beans. The framework provides many implementations of factory beans and -- when using Spring's XML config -- factory beans are easy to use.

However, in Spring 3.0, I can't find a satisfactory way of using factory beans with the annotation-based configuration (née JavaConfig).

Obviously, I could manually instantiate the factory bean and set any required properties myself, like so:

@Configuration public class AppConfig {  ...      @Bean     public SqlSessionFactory sqlSessionFactory() throws Exception {         SqlSessionFactoryBean factory = new SqlSessionFactoryBean();         factory.setDataSource(dataSource());         factory.setAnotherProperty(anotherProperty());          return factory.getObject();     } 

However, this would fail if the FactoryBean implemented any Spring-specific callback interfaces, like InitializingBean, ApplicationContextAware, BeanClassLoaderAware, or @PostConstruct for example. I also need to inspect the FactoryBean, find out what callback interfaces it implements, then implement this functionality myself by calling setApplicationContext, afterPropertiesSet() etc.

This feels awkward and back-to-front to me: application-developers should not have to implement the callbacks of the IOC container.

Does anyone know of a better solution to using FactoryBeans from Spring Annotation configs?

like image 578
Andrew Newdigate Avatar asked Apr 04 '11 15:04

Andrew Newdigate


People also ask

What is annotation based configuration in Spring?

What is Spring Annotation Based Configuration? In Spring Framework annotation-based configuration instead of using XML for describing the bean wiring, you have the choice to move the bean configuration into component class. It is done by using annotations on the relevant class, method or the field declaration.

Which of these can be used in Java based or annotation based Spring configuration?

Using Java based configuration allows you to write your Spring configuration without using XML. These annotations will be explained to you with working example using Eclipse IDE. Some of these annotations are: @Configuration and @Bean annotations.

Which tag requires configuration files in order to enable annotation in the Spring application?

The <context:annotation-config> annotation is mainly used to activate the dependency injection annotations. @Autowired, @Qualifier, @PostConstruct, @PreDestroy, and @Resource are some of the ones that <context:annotation-config> can resolve.

Which annotation do you use @qualifier with?

The @Qualifier annotation can be used on any class annotated with @Component or on methods annotated with @Bean . This annotation can also be applied on constructor arguments or method parameters. Injecting Bike bean in VehicleService using @Autowired with @Qualifier annotation.


2 Answers

I think that this is best solved when you rely on auto-wiring. If you are using Java configuration for the beans, this would like:

@Bean MyFactoryBean myFactory() {      // this is a spring FactoryBean for MyBean     // i.e. something that implements FactoryBean<MyBean>     return new MyFactoryBean(); }  @Bean MyOtherBean myOther(final MyBean myBean) {     return new MyOtherBean(myBean); } 

So Spring will inject for us the MyBean instance returned by the myFactory().getObject() as it does with XML configuration.

This should also work if you are using @Inject/@Autowire in your @Component/@Service etc classes.

like image 50
tsachev Avatar answered Sep 28 '22 05:09

tsachev


As far as I understand your problem is what you want a result of sqlSessionFactory() to be a SqlSessionFactory (for use in other methods), but you have to return SqlSessionFactoryBean from a @Bean-annotated method in order to trigger Spring callbacks.

It can be solved with the following workaround:

@Configuration  public class AppConfig {      @Bean(name = "sqlSessionFactory")     public SqlSessionFactoryBean sqlSessionFactoryBean() { ... }      // FactoryBean is hidden behind this method     public SqlSessionFactory sqlSessionFactory() {         try {             return sqlSessionFactoryBean().getObject();         } catch (Exception ex) {             throw new RuntimeException(ex);         }     }      @Bean     public AnotherBean anotherBean() {         return new AnotherBean(sqlSessionFactory());     } } 

The point is that calls to @Bean-annotated methods are intercepted by an aspect which performs initialization of the beans being returned (FactoryBean in your case), so that call to sqlSessionFactoryBean() in sqlSessionFactory() returns a fully initialized FactoryBean.

like image 32
axtavt Avatar answered Sep 28 '22 05:09

axtavt