From 634d4b4d4c263f6a734fed142fa15ca48acb9262 Mon Sep 17 00:00:00 2001 From: Juergen Hoeller Date: Tue, 8 Sep 2009 23:01:26 +0000 Subject: [PATCH] BeanFactory prefers local primary bean to primary bean in parent factory (SPR-5871) --- .../support/DefaultListableBeanFactory.java | 15 ++++++++-- .../xml/AutowireWithExclusionTests.java | 28 +++++++++++++++---- 2 files changed, 34 insertions(+), 9 deletions(-) diff --git a/org.springframework.beans/src/main/java/org/springframework/beans/factory/support/DefaultListableBeanFactory.java b/org.springframework.beans/src/main/java/org/springframework/beans/factory/support/DefaultListableBeanFactory.java index e5869b0e1c1..52211c2fd20 100644 --- a/org.springframework.beans/src/main/java/org/springframework/beans/factory/support/DefaultListableBeanFactory.java +++ b/org.springframework.beans/src/main/java/org/springframework/beans/factory/support/DefaultListableBeanFactory.java @@ -808,10 +808,19 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto Object beanInstance = entry.getValue(); if (isPrimary(candidateBeanName, beanInstance)) { if (primaryBeanName != null) { - throw new NoSuchBeanDefinitionException(descriptor.getDependencyType(), - "more than one 'primary' bean found among candidates: " + candidateBeans.keySet()); + boolean candidateLocal = containsBeanDefinition(candidateBeanName); + boolean primaryLocal = containsBeanDefinition(primaryBeanName); + if (candidateLocal == primaryLocal) { + throw new NoSuchBeanDefinitionException(descriptor.getDependencyType(), + "more than one 'primary' bean found among candidates: " + candidateBeans.keySet()); + } + else if (candidateLocal && !primaryLocal) { + primaryBeanName = candidateBeanName; + } + } + else { + primaryBeanName = candidateBeanName; } - primaryBeanName = candidateBeanName; } if (primaryBeanName == null && (this.resolvableDependencies.values().contains(beanInstance) || diff --git a/org.springframework.beans/src/test/java/org/springframework/beans/factory/xml/AutowireWithExclusionTests.java b/org.springframework.beans/src/test/java/org/springframework/beans/factory/xml/AutowireWithExclusionTests.java index f731fb97f31..e13d3881781 100644 --- a/org.springframework.beans/src/test/java/org/springframework/beans/factory/xml/AutowireWithExclusionTests.java +++ b/org.springframework.beans/src/test/java/org/springframework/beans/factory/xml/AutowireWithExclusionTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2008 the original author or authors. + * Copyright 2002-2009 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,18 +16,16 @@ package org.springframework.beans.factory.xml; -import junit.framework.TestCase; import junit.framework.Assert; +import junit.framework.TestCase; +import test.beans.TestBean; import org.springframework.beans.factory.config.PropertiesFactoryBean; import org.springframework.beans.factory.config.RuntimeBeanReference; -import org.springframework.beans.factory.support.AbstractBeanDefinition; import org.springframework.beans.factory.support.DefaultListableBeanFactory; import org.springframework.beans.factory.support.RootBeanDefinition; import org.springframework.core.io.ClassPathResource; -import test.beans.TestBean; - /** * @author Rob Harrop * @author Juergen Hoeller @@ -69,7 +67,7 @@ public class AutowireWithExclusionTests extends TestCase { public void testByTypeAutowireWithPrimaryInParentFactory() throws Exception { CountingFactory.reset(); XmlBeanFactory parent = getBeanFactory("autowire-with-exclusion.xml"); - ((AbstractBeanDefinition) parent.getBeanDefinition("props1")).setPrimary(true); + parent.getBeanDefinition("props1").setPrimary(true); parent.preInstantiateSingletons(); DefaultListableBeanFactory child = new DefaultListableBeanFactory(parent); RootBeanDefinition robDef = new RootBeanDefinition(TestBean.class, RootBeanDefinition.AUTOWIRE_BY_TYPE); @@ -100,6 +98,24 @@ public class AutowireWithExclusionTests extends TestCase { Assert.assertEquals(1, CountingFactory.getFactoryBeanInstanceCount()); } + public void testByTypeAutowireWithPrimaryInParentAndChild() throws Exception { + CountingFactory.reset(); + XmlBeanFactory parent = getBeanFactory("autowire-with-exclusion.xml"); + parent.getBeanDefinition("props1").setPrimary(true); + parent.preInstantiateSingletons(); + DefaultListableBeanFactory child = new DefaultListableBeanFactory(parent); + RootBeanDefinition robDef = new RootBeanDefinition(TestBean.class, RootBeanDefinition.AUTOWIRE_BY_TYPE); + robDef.getPropertyValues().addPropertyValue("spouse", new RuntimeBeanReference("sally")); + child.registerBeanDefinition("rob2", robDef); + RootBeanDefinition propsDef = new RootBeanDefinition(PropertiesFactoryBean.class); + propsDef.getPropertyValues().addPropertyValue("properties", "name=props3"); + propsDef.setPrimary(true); + child.registerBeanDefinition("props3", propsDef); + TestBean rob = (TestBean) child.getBean("rob2"); + assertEquals("props3", rob.getSomeProperties().getProperty("name")); + Assert.assertEquals(1, CountingFactory.getFactoryBeanInstanceCount()); + } + public void testByTypeAutowireWithInclusion() throws Exception { CountingFactory.reset(); XmlBeanFactory beanFactory = getBeanFactory("autowire-with-inclusion.xml");