Announcement Announcement Module
Collapse
No announcement yet.
AbstractBeanFactory.getBean(String name, Object[] args) issue workaround Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • AbstractBeanFactory.getBean(String name, Object[] args) issue workaround

    This is a proposed workaround for Spring 2.5.6 for this issue (SPR-5790). AbstractBeanFactory.getBean(String name, Object [] args) does not work in conjunction with AbstractBeanFactory.getBean(String name) - you get inconsistent behaviour where the default constructor of your (prototype) bean is called instead of the custom constructor.

    Feel free to suggest improvements/simplifications. We are currently unable to move to the Spring 3 version in which this is fixed, and it doesn't look it like it will be back-ported, so the workaround is necessary.

    Integration Testing

    Add the following override to your test or base test class.

    Code:
        @Override
        protected ConfigurableApplicationContext createApplicationContext(String[] locations) {
            GenericApplicationContext context = new GenericApplicationContext(new CustomBeanFactory());
            prepareApplicationContext(context);
            customizeBeanFactory(context.getDefaultListableBeanFactory());
            createBeanDefinitionReader(context).loadBeanDefinitions(locations);
            context.refresh();
            return context;
        }
    CustomBeanFactory: override the faulty method (as per the fix). This must be placed in a org.springframework.beans.factory.support package of your own.
    Code:
    @Override
    protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, Object[] args) {
                // Make sure bean class is actually resolved at this point.
                Class beanClass = resolveBeanClass(mbd, beanName);
    
                if (mbd.getFactoryMethodName() != null)  {
                        return instantiateUsingFactoryMethod(beanName, mbd, args);
                }
    
                // Shortcut when re-creating the same bean...
                if (mbd.resolvedConstructorOrFactoryMethod != null && args == null) {
                        if (mbd.constructorArgumentsResolved) {
                                return autowireConstructor(beanName, mbd, null, args);
                        }
                        else {
                                return instantiateBean(beanName, mbd);
                        }
                }
    
                // Need to determine the constructor...
                Constructor[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
                if (ctors != null ||
                                mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR ||
                                mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args))  {
                        return autowireConstructor(beanName, mbd, ctors, args);
                }
    
                // No special handling: simply use no-arg constructor.
                return instantiateBean(beanName, mbd);
        }
    Production

    CustomClasspathXmlApplicationContext: override the createBeanFactory() method.
    Code:
        @Override
        protected DefaultListableBeanFactory createBeanFactory() {
            return new CustomBeanFactory(getInternalParentBeanFactory());
        }
    You will also need to use the custom application context, so you might have a method like the following:

    Code:
        public static ApplicationContext getContext() {
            if (null == ctx) {
                ctx = new CustomClassPathXmlApplicationContext(contexts);
            }
            return ctx;
        }
    Last edited by virgo_ct; Sep 22nd, 2009, 05:44 AM.
Working...
X