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?