Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Get new instance of a spring bean

I have an interface called MyInterface. The class that implements MyInterface (lets call it MyImplClass) also implements the Runnable interface so i can use it to instantiate threads. This is my code now.

for (OtherClass obj : someList) {
    MyInterface myInter = new MyImplClass(obj);
    Thread t = new Thread(myInter);
    t.start();
} 

What i want to do is to declare the implementing class in my ApplicationContext.xml and get a new instance for each iteration. So my code will look something like this:

for (OtherClass obj : someList) {
    MyInterface myInter = // getting the implementation from elsewhere
    Thread t = new Thread(myInter);
    t.start();
} 

I want to still keep the IoC pattern if possible.
How can i do so?
Thanks

like image 274
Mr T. Avatar asked Apr 07 '15 15:04

Mr T.


Video Answer


3 Answers

You can try factory pattern with spring scope prototype like below. Define a Abstract Factory Class which will give you MyInterface object

public abstract class MyInterfaceFactoryImpl implements MyInterfaceFactory {

@Override
public abstract MyInterface getMyInterface();

}

Then define the Spring bean.xml file as below. Please note myinterface bean is defined as prototype ( So it will always give you new instance).

<bean name="myinterface" class="com.xxx.MyInterfaceImpl" scope="prototype"/>

Then define the factorybean with factory method name.

<bean name="myinterfaceFactory" class="com.xxx.MyInterfaceFactoryImpl">
    <lookup-method bean="myinterface" name="getMyInterface" />
</bean>

Now you can call myinterfaceFactory to get new instance.

for (OtherClass obj : someList) {
        MyInterface myInter = myInterfaceFactory.getMyInterface();
        Thread t = new Thread(myInter);
        t.start();
}
like image 170
Himanshu Ahire Avatar answered Oct 21 '22 13:10

Himanshu Ahire


Keep the spring configuration file, beans.xml in the root of the classpath. Making scope=prototype, will result in different instances of bean for each getBean method invocation.

beans.xml

<?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="myinterface" class="MyImplClass" scope="prototype"/>
</beans>

Similar way if you want Spring to return the same bean instance each time one is needed, you should declare the bean's scope attribute to be singleton.

Once the IoC container is initialized, you can retrieve your Spring beans. But make sure, you do the below only initialization only once.

ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");

Then you can change your code as below.

for (OtherClass obj : someList) {
MyInterface myInter = (MyInterface ) context.getBean("myinterface");
Thread t = new Thread(myInter);
t.start();
}
like image 27
Albin Avatar answered Oct 21 '22 11:10

Albin


Given the context you provided in your comment to me, I would suggest you don't have the MyImplClass instances created by Spring. Having this prototyped object instantiated by Spring provides no benefit from what I can tell.

The best way, in my opinion, to keep with the IoC pattern here would be to instead utilize a Spring managed Factory that produces instances of MyImplClass. Something along the lines of this:

public class MyInterfaceFactory {
    public MyInterface newInstance(final OtherClass o) {
        return new MyImplClass(o);
    }
}

Depending on the usage needs, you can modify this factory's interface to return MyImplClass, or add some logic to return a different implementation of MyInterface.

I tend to think that Factories and IoC/DI work pretty well together, and your use case is a pretty good example of that.

like image 22
nicholas.hauschild Avatar answered Oct 21 '22 11:10

nicholas.hauschild