Spring 2.5.x+3.0.x: Create prototype instances from code
Here follow some snippets to show you the programmatically creation of prototype instances using Spring 2.5.6.SEC01.
a) Create a spring bean with scope “prototype”.
package springsample;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
@Component
@Scope(value = "prototype")
public class Knife {
}
b) Create a spring bean and autowire a ProviderUtil instance (l. 12). The prototype instances are created at line 29 using ProviderUtils.
package springsample;
import java.util.ArrayList;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class KnifeJuggler {
@Autowired
ProviderUtil util;
public void juggle() {
List<Knife> list = new ArrayList<Knife>();
for (int i = 0; i < 5; i++) {
//create 5 prototype scoped instances
list.add(createKnifeInstance());
}
//print each instance
for (Knife knife : list) {
System.out.println(knife);
}
}
private Knife createKnifeInstance() {
return util.getBeanByType(Knife.class);
}
}
c) The “magic” is coded here. A utility bean named ProviderUtil is defined and the ApplicationContext is autowired (l. 14). The prototype bean now can be resolved using this context: Every time you call ctx.getBean(xxx) to get the bean a new instance will be returned (l. 24). (Because the scope of the target bean is “prototype”)
package springsample;
import java.util.Map;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.stereotype.Component;
@Component
public class ProviderUtil {
@Autowired
private ApplicationContext ctx;
public <T> T getBeanByType(final Class<T> claz) throws UnsupportedOperationException, BeansException {
Map beansOfType = ctx.getBeansOfType(claz);
final int size = beansOfType.size();
switch (size) {
case 0:
throw new UnsupportedOperationException("No bean found of type" + claz);
case 1:
String name = (String) beansOfType.keySet().iterator().next();
return claz.cast(ctx.getBean(name, claz));
default:
throw new UnsupportedOperationException("Ambigious beans found of type" + claz);
}
}
}
d) Enable annotation driven spring bean processing. This registers all Spring beans via annotations like @Component.
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-2.5.xsd"
>
<context:component-scan base-package="springsample"/>
</beans>
e) Sample code to test these snippets
package springsample;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Main {
public static void main(String[] args) {
ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("newSpringXMLConfig.xml");
//resolve by type
KnifeJuggler juggler = ProviderUtil.getBeanByType(ctx, KnifeJuggler.class);
juggler.juggle();
}
}
e) When running this code 5 different prototype instance will be printed to stdout.
springsample.Knife@f9da4fc
springsample.Knife@36baa466
springsample.Knife@177f409c
springsample.Knife@236acdd1
springsample.Knife@38ee6681
BUILD SUCCESSFUL (total time: 0 seconds)
Alternative a) An alternative would be the usage of
javax.inject.Provider from JSR 330, but this is not supported for Spring 2.5.x. Using javax.inject.Provider in Spring 3.0.6 works. Do not forget to include a JSR330-dependency (like JEE6-API in NetBeans).
The code is simpler again: Autowire a provider for the prototype bean (l. 13) and use the provider to get the prototype instance (l. 31).
package springsample;
import java.util.ArrayList;
import java.util.List;
import javax.inject.Provider;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component(value = "jugglername")
public class KnifeJuggler {
@Autowired
Provider<Knife> knifeProvider;
public void juggle() {
List<Knife> list = new ArrayList<Knife>();
for (int i = 0; i < 5; i++) {
//create 5 prototype scoped instances
list.add(createKnifeInstance());
}
//print each instance
for (Knife knife : list) {
System.out.println(knife);
}
}
private Knife createKnifeInstance() {
return knifeProvider.get();
}
}
Alternative b) Use ObjectFactory – see the sample at http://techo-ecco.com/blog/spring-prototype-scoped-beans-and-dependency-injection/
Recent Comments