이 콘텐츠는 선택한 언어로 제공되지 않습니다.
7.7. Bean Factory
When you want more than one instance of a particular bean, you need to use the bean factory pattern. The job of the Microcontainer is to configure and install the bean factory as if it were a plain bean. Then you need to invoke the bean factory's
createBean
method.
By default, the Microcontainer creates a
GenericBeanFactory
instance, but you can configure your own factory. The only limitation is that its signature and configuration hooks are similar to the one of AbstractBeanFactory
.
Example 7.15. Generic Bean Factory
<bean name="Object" class="java.lang.Object"/> <beanfactory name="DefaultPrototype" class="org.jboss.demos.ioc.factory.Prototype"> <property name="value"><inject bean="Object"/></property> </beanfactory> <beanfactory name="EnhancedPrototype" class="org.jboss.demos.ioc.factory.Prototype" factoryClass="org.jboss.demos.ioc.factory.EnhancedBeanFactory"> <property name="value"><inject bean="Object"/></property> </beanfactory> <beanfactory name="ProxiedPrototype" class="org.jboss.demos.ioc.factory.UnmodifiablePrototype" factoryClass="org.jboss.demos.ioc.factory.EnhancedBeanFactory"> <property name="value"><inject bean="Object"/></property> </beanfactory> <bean name="PrototypeCreator" class="org.jboss.demos.ioc.factory.PrototypeCreator"> <property name="default"><inject bean="DefaultPrototype"/></property> <property name="enhanced"><inject bean="EnhancedPrototype"/></property> <property name="proxied"><inject bean="ProxiedPrototype"/></property> </bean>
<bean name="Object" class="java.lang.Object"/>
<beanfactory name="DefaultPrototype" class="org.jboss.demos.ioc.factory.Prototype">
<property name="value"><inject bean="Object"/></property>
</beanfactory>
<beanfactory name="EnhancedPrototype" class="org.jboss.demos.ioc.factory.Prototype" factoryClass="org.jboss.demos.ioc.factory.EnhancedBeanFactory">
<property name="value"><inject bean="Object"/></property>
</beanfactory>
<beanfactory name="ProxiedPrototype" class="org.jboss.demos.ioc.factory.UnmodifiablePrototype" factoryClass="org.jboss.demos.ioc.factory.EnhancedBeanFactory">
<property name="value"><inject bean="Object"/></property>
</beanfactory>
<bean name="PrototypeCreator" class="org.jboss.demos.ioc.factory.PrototypeCreator">
<property name="default"><inject bean="DefaultPrototype"/></property>
<property name="enhanced"><inject bean="EnhancedPrototype"/></property>
<property name="proxied"><inject bean="ProxiedPrototype"/></property>
</bean>
See Example 7.16, “Extended BeanFactory” for usage of an extended BeanFactory.
Example 7.16. Extended BeanFactory
public class EnhancedBeanFactory extends GenericBeanFactory { public EnhancedBeanFactory(KernelConfigurator configurator) { super(configurator); } public Object createBean() throws Throwable { Object bean = super.createBean(); Class clazz = bean.getClass(); if (clazz.isAnnotationPresent(SetterProxy.class)) { Set<Class> interfaces = new HashSet<Class>(); addInterfaces(clazz, interfaces); return Proxy.newProxyInstance( clazz.getClassLoader(), interfaces.toArray(new Class[interfaces.size()]), new SetterInterceptor(bean) ); } else { return bean; } } protected static void addInterfaces(Class clazz, Set<Class> interfaces) { if (clazz == null) return; interfaces.addAll(Arrays.asList(clazz.getInterfaces())); addInterfaces(clazz.getSuperclass(), interfaces); } private class SetterInterceptor implements InvocationHandler { private Object target; private SetterInterceptor(Object target) { this.target = target; } public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { String methodName = method.getName(); if (methodName.startsWith("set")) throw new IllegalArgumentException("Cannot invoke setters."); return method.invoke(target, args); } } }
public class EnhancedBeanFactory extends GenericBeanFactory {
public EnhancedBeanFactory(KernelConfigurator configurator)
{
super(configurator);
}
public Object createBean() throws Throwable
{
Object bean = super.createBean();
Class clazz = bean.getClass();
if (clazz.isAnnotationPresent(SetterProxy.class))
{
Set<Class> interfaces = new HashSet<Class>();
addInterfaces(clazz, interfaces);
return Proxy.newProxyInstance(
clazz.getClassLoader(),
interfaces.toArray(new Class[interfaces.size()]),
new SetterInterceptor(bean)
);
}
else
{
return bean;
}
}
protected static void addInterfaces(Class clazz, Set<Class> interfaces)
{
if (clazz == null)
return;
interfaces.addAll(Arrays.asList(clazz.getInterfaces()));
addInterfaces(clazz.getSuperclass(), interfaces);
}
private class SetterInterceptor implements InvocationHandler
{
private Object target;
private SetterInterceptor(Object target)
{
this.target = target;
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
{
String methodName = method.getName();
if (methodName.startsWith("set"))
throw new IllegalArgumentException("Cannot invoke setters.");
return method.invoke(target, args);
}
}
}
public class PrototypeCreator { ... public void create() throws Throwable { ValueInvoker vi1 = (ValueInvoker)bfDefault.createBean(); vi1.setValue("default"); ValueInvoker vi2 = (ValueInvoker)enhanced.createBean(); vi2.setValue("enhanced"); ValueInvoker vi3 = (ValueInvoker)proxied.createBean(); try { vi3.setValue("default"); throw new Error("Should not be here."); } catch (Exception ignored) { } }
public class PrototypeCreator {
...
public void create() throws Throwable
{
ValueInvoker vi1 = (ValueInvoker)bfDefault.createBean();
vi1.setValue("default");
ValueInvoker vi2 = (ValueInvoker)enhanced.createBean();
vi2.setValue("enhanced");
ValueInvoker vi3 = (ValueInvoker)proxied.createBean();
try
{
vi3.setValue("default");
throw new Error("Should not be here.");
}
catch (Exception ignored)
{
}
}