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
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();
}
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();
}
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With