Search code examples
javaxmlspringspring-annotations

Spring prototype bean reference in Spring @Configuration


I went through the following page to bootstrap an applicationContext.xml in Java.

http://docs.spring.io/spring-javaconfig/docs/1.0.0.M4/reference/html/ch06.html

My applicationContext has something like:

<beans>
    <bean id="foo" class="com.mypackage.Foo" scope="prototype">       
    </bean>
</beans>

I need to refer to "foo" in Java as follows:

@Configuration
@AnnotationDrivenConfig 
@ImportXml("classpath:applicationContext.xml")
public class Config {

    @Autowired Foo foo;

    @Bean(name="fooRepository")
    @Scope("prototype")
    public FooRepository fooRepository() {
        return new JdbcFooRepository(foo);
    }


}

I am creating a reference of FooRepository as follows:

ApplicationContext ctx = 
                   new AnnotationConfigApplicationContext(Config.class);

FooRepository fr = ctx.getBean("fooRepository", FooRepository.class);

Every time I invoke it, I get a new instance of FooRepository which is defined as "prototype" and this is fine with me.

But when an instance of FooRepository is returned I see the same instance of "foo" is used though "foo" in the XML file is "prototype".

  1. How do I set Foo as new instance all the time to FooRepository when FooRepository is created?
  2. The instance of Foo should be from the XML file.

Solution

  • You need to remove the entry of Foo from xml. You can define it this way.

    @Configuration
    @AnnotationDrivenConfig
    @ImportXml("classpath:applicationContext.xml")
    public class Config {
    
        @Bean(name = "fooRepository")
        @Scope("prototype")
        public FooRepository fooRepository() {
            return new JdbcFooRepository(foo());
        }
    
        @Bean(name = "foo")
        @Scope("prototype")
        public Foo foo() {
            return new foo();
        }
    }
    

    Approach 2: You can refer this SO Answer.

    @Configuration
    @AnnotationDrivenConfig
    @ImportXml("classpath:applicationContext.xml")
    public class Config {
    
        @Autowired
        private ApplicationContext context;
    
        @Bean(name = "fooRepository")
        @Scope("prototype")
        public FooRepository fooRepository() {
            return new JdbcFooRepository(context.getBean("foo", Foo.class));
        }
    }