Reputation: 1397
I have a factory that creates instances:
public class myFactory {
public static getInstace() {
switch(someInt) {
case 1:
return new MySpringBean();
case 2:
return new MyOtherSpringBean();
}
}
}
I need to return a new instance of the beans that are "managed" by Spring bc they have Transactional business logic methods. I have read in many posts here that I should not use getBean method to get a singleton or a new instance from the applicationContext. But I cannot find the proper way to do it for my case. I have used @Resource and it seems to work but it doesn't support static fields. Thanx
Upvotes: 0
Views: 2783
Reputation: 22509
You implement the org.springframework.beans.factory.FactoryBean
interface for objects that are themselves factories.
The FactoryBean interface is a point of pluggability into the Spring IoC container's instantiation logic. If you have complex initialization code that is better expressed in Java as opposed to a (potentially) verbose amount of XML, you can create your own FactoryBean, write the complex initialization inside that class, and then plug your custom FactoryBean into the container.
The FactoryBean interface provides three methods:
Object getObject()
: returns an instance of the object this factory creates. The instance can possibly be shared, depending on whether this factory returns singletons or prototypes.
boolean isSingleton()
: returns true if this FactoryBean returns singletons, false otherwise.
Class getObjectType()
: returns the object type returned by the getObject() method or null if the type is not known in advance
Take a look at Spring Docs
Upvotes: 0
Reputation: 10720
One way is create a factory class and store the instances of the beans (each implementing a common interface MyBean
) as values under some key in a map (beans
):
public class MyBeanFactory {
private Map<Integer, MyBean> beans;
public MyBean create(Integer which) {
if (which != null)
return beans.get(which);
else
throw new IllegalArgumentException("Unknown bean");
}
public void setBeans(Map<Integer, MyBean> beans) {
this.beans = beans;
}
}
In your Spring applicationContext.xml
now create bean a of the factory and set the beans:
<beans...>
<bean id="myBeanFactory" class="foo.bar.MyBeanFactory">
<property name="beans">
<map>
<entry key="1">
<bean class="foo.bar.MyBeanA" />
</entry>
<entry key="2">
<bean class="foo.bar.MyBeanB" />
</entry>
</map>
</property>
</bean>
</beans>
Finally you can inject your bean factory as usual and get instances from like e.g. this:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "classpath:/applicationContext.xml" })
public class MyBeanFactoryTest {
@Autowired
private MyBeanFactory myBeanFactory;
@Test
public void test() {
Assert.assertTrue(myBeanFactory.create(1) instanceof MyBeanA);
Assert.assertTrue(myBeanFactory.create(2) instanceof MyBeanB);
}
}
Upvotes: 0
Reputation: 29619
There are many ways to achieve this in spring, the most obvious way given the factory class that you have is to use JavaConfig. If you used the spring enabled JavaConfig annotations you could do the following to construct your beans and add them to the application context:
@Configuration
public class myFactory {
@Bean
public static getInstance() {
switch(someInt) {
case 1:
return new MySpringBean();
case 2:
return new MyOtherSpringBean();
}
}
}
Upvotes: 2