Lazy bean behaviour
alesj Oct 8, 2007 6:34 PMI'm doing (apart from AS5_PS ... no worries ;-)) some GUI example console for MC and was missing the following feature - lazy 'instantiation/install' of the bean.
e.g. I have some service that has many dependencies - many injected beans. One of them is rarely used and/or is fully installed in some later-on deployment unit. But I would still like to have that first service up and running.
So, I hacked a lazy notion to our beans - lazy proxies.
What you can do now is the following XML
<bean name="bean" class="org.jboss.test.kernel.lazy.support.RareBean"/> <lazy name="proxy" bean="bean" exposeClass="true"> <interface>org.jboss.test.kernel.lazy.support.IRare</interface> </lazy>
or the straight API
AbstractLazyMetaData lazy = new AbstractLazyMetaData("bean");
lazy.setInterfaces(Collections.singleton(IRare.class.getName()));
And the test to show that lazyness :-)
AbstractBeanMetaData bean = new AbstractBeanMetaData("bean", RareBean.class.getName());
bean.setMode(ControllerMode.MANUAL);
KernelControllerContext beanContext = controller.install(bean);
controller.change(beanContext, ControllerState.NOT_INSTALLED);
ModifiedLazyMetaData lazy = new ModifiedLazyMetaData("bean", getFactoryClassName());
lazy.setInterfaces(Collections.singleton(IRare.class.getName()));
KernelControllerContext lazyContext = controller.install(lazy);
assertNotNull(lazyContext);
assertEquals(ControllerState.DESCRIBED, lazyContext.getState());
controller.change(beanContext, ControllerState.DESCRIBED);
controller.change(lazyContext, ControllerState.INSTALLED);
IRare lazyRare = (IRare)lazyContext.getTarget();
assertNotNull(lazyRare);
try
{
lazyRare.getHits();
throw new RuntimeException("Should not be here.");
}
catch(Throwable t)
{
assertInstanceOf(t, IllegalArgumentException.class);
}
controller.change(beanContext, ControllerState.INSTALLED);
assertEquals(0, lazyRare.getHits());
lazyRare.setHits(10);
assertEquals(5, lazyRare.checkHits(15));
The code checks for the first available proxy generator - Javassist, JBossAOP (wip), JDK, ... (possible additions CGLIB, ASM, ...)
static
{
initializerMap = new LinkedHashMap<String, String>();
// test class name, actual LazyInitializer implementation
initializerMap.put("javassist.util.proxy.ProxyObject", "org.jboss.kernel.plugins.lazy.JavassistLazyInitializer");
initializerMap.put("org.jboss.aop.proxy.container.AOPProxyFactoryParameters", "org.jboss.aop.microcontainer.lazy.JBossAOPLazyInitializer");
initializerMap.put("java.lang.reflect.Proxy", "org.jboss.kernel.plugins.lazy.JDKLazyInitializer");
}
/**
* Get the LazyInitializater instance.
*
* @param configurator the configurator
* @return initializer instance
*/
protected static LazyInitializer getInitializer(KernelConfigurator configurator)
{
if (initializer == null)
{
for(Map.Entry<String, String> entry : initializerMap.entrySet())
{
if (testLibExists(entry.getKey()))
{
initializer = createInitializer(configurator, entry.getValue());
if (initializer != null)
break;
}
}
}
if (initializer == null)
throw new IllegalArgumentException("Cannot initialize LazyInitializater, check classpath for missing classes.");
return initializer;
}
The proxies use KernelBus to do the invocation.
Currently you need to specify which interfaces are exposed.
Perhaps this can be done automa(g|t)ically?