I thought I'd see if a very simple approach toward RTDI is possible.
My idea is that the interval used by BeanPostProcessor could be used to invoke an injector on a bean. To not require any new interfaces on the bean, the injection hookup is done with an approach similar to proxy use. But, really its just a Visitor pattern.
It works, at least a simple unit test proves it, but it still doesn't really solve the RTDI problem for me. I can't use it, and I'm sure there are better Springish ways to go about it, but maybe someone will find it useful or it may inspire a better approach.Code:/** * RunTime Dependency Injector interface. * The Visitor of the Visitor pattern. * * May 3, 2005 * @author JBETANCOURT * */ public interface RTDI { /** * @param bean */ void inject(Object bean); } /** * A BeanPostProcessor for invoking an object that supplies run-time * configuration to another object. * This uses the Visitor pattern. But, see existing Spring API * for approaches such as:<p/> * * @see org.springframework.beans.factory.config.ServiceLocatorFactoryBean * @see org.springframework.beans.factory.support.AbstractBeanFactory.getBean(...) * @see org.springframework.beans.factory.config.ServiceCreationFactoryBean (in * Sandbox) * @see org.springframework.beans.factory.config.BeanPostProcessor.html * <p/> * NOTE: TO SAVE SPACE LEFT OUT CLASS DETAILS * <p/> * * * Example context definition: * <pre> * <beans> * * <bean id="clientOne" class="Client"/> * <bean id="injectorOne" class="Injector"/> * * <bean id="rtdiBean" class="RTDIPostProcessor"> * <property name="beanNames"> * <list> * <value>clientOne</value> * </list> * </property> * <property name="injectorNames"> * <list> * <value>injectorOne</value> * </list> * </property> * * </bean> * * </beans> * </pre> * * * May 3, 2005 * * @author JBETANCOURT * */ public class RTDIPostProcessor implements BeanPostProcessor, ApplicationContextAware { /** which beans will be post processed */ List beanNames; // /** list of RTDI bean names that will apply the post processing. */ List injectorNames; /** where we pull the injector from */ private ApplicationContext ctx; public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { if (injectorNames.isEmpty() || beanNames.isEmpty()) { return bean; } if (beanNames.contains(beanName)) { for (Iterator iter = injectorNames.iterator(); iter.hasNext();) { String visitorName = (String) iter.next(); RTDI visitor = (RTDI) ctx.getBean(visitorName); // in this invocation the visitor must determine the actual rtti of bean. visitor.inject(bean); // // alternativly, use reflection to invoke. // Method method = BeanUtils.findDeclaredMethod( // visitor.getClass(), INJECT_METHOD_NAME, new Class[] { bean // .getClass() }); // // TODO: fault handling ... // try { // method.invoke(visitor, new Object[] { bean }); // } catch (InvocationTargetException e) { // throw e.getCause(); // } } } return bean; } }


Reply With Quote