From 76d0b9794aced8274b768141336b20e0e5ce616d Mon Sep 17 00:00:00 2001 From: Jose Luis Martin Date: Fri, 18 Oct 2013 21:01:50 +0200 Subject: [PATCH] Skip already added bean methods from superclass When adding bean methods from a Configuration class, overridden methods from superclass are added too and it's bean definition overrides those declared in the subclass. The fix add a new method, getBeanMethodsToDefine that filter overriden methods for use in ConfigurationClassBeanDefinitionReader Issue: SPR-10992 --- .../annotation/ConfigurationClass.java | 21 ++++++ ...onfigurationClassBeanDefinitionReader.java | 2 +- .../ConfigurationClassInheritanceTest.java | 65 +++++++++++++++++++ 3 files changed, 87 insertions(+), 1 deletion(-) create mode 100644 spring-context/src/test/java/org/springframework/context/annotation/configuration/ConfigurationClassInheritanceTest.java diff --git a/spring-context/src/main/java/org/springframework/context/annotation/ConfigurationClass.java b/spring-context/src/main/java/org/springframework/context/annotation/ConfigurationClass.java index 38f6aaac2ba5..748a63f0d156 100644 --- a/spring-context/src/main/java/org/springframework/context/annotation/ConfigurationClass.java +++ b/spring-context/src/main/java/org/springframework/context/annotation/ConfigurationClass.java @@ -18,6 +18,7 @@ import java.util.Collections; import java.util.HashMap; +import java.util.HashSet; import java.util.LinkedHashMap; import java.util.LinkedHashSet; import java.util.Map; @@ -172,6 +173,26 @@ public void addBeanMethod(BeanMethod method) { public Set getBeanMethods() { return this.beanMethods; } + + /** + * Gets bean methods elegibles for bean definitions + * skipping overriden methods from superclasses. + */ + public Set getBeanMethodsToDefine() { + Set methods = new LinkedHashSet(); + Set names = new HashSet(); + + for (BeanMethod method : beanMethods) { + String name = method.getMetadata().getMethodName(); + if (!names.contains(name)) { + methods.add(method); + names.add(name); + } + } + + return methods; + } + public void addImportedResource(String importedResource, Class readerClass) { this.importedResources.put(importedResource, readerClass); diff --git a/spring-context/src/main/java/org/springframework/context/annotation/ConfigurationClassBeanDefinitionReader.java b/spring-context/src/main/java/org/springframework/context/annotation/ConfigurationClassBeanDefinitionReader.java index c47d43f97c2b..7155e3bc572a 100644 --- a/spring-context/src/main/java/org/springframework/context/annotation/ConfigurationClassBeanDefinitionReader.java +++ b/spring-context/src/main/java/org/springframework/context/annotation/ConfigurationClassBeanDefinitionReader.java @@ -132,7 +132,7 @@ private void loadBeanDefinitionsForConfigurationClass(ConfigurationClass configC if (configClass.isImported()) { registerBeanDefinitionForImportedConfigurationClass(configClass); } - for (BeanMethod beanMethod : configClass.getBeanMethods()) { + for (BeanMethod beanMethod : configClass.getBeanMethodsToDefine()) { loadBeanDefinitionsForBeanMethod(beanMethod); } loadBeanDefinitionsFromImportedResources(configClass.getImportedResources()); diff --git a/spring-context/src/test/java/org/springframework/context/annotation/configuration/ConfigurationClassInheritanceTest.java b/spring-context/src/test/java/org/springframework/context/annotation/configuration/ConfigurationClassInheritanceTest.java new file mode 100644 index 000000000000..e11ee02c3030 --- /dev/null +++ b/spring-context/src/test/java/org/springframework/context/annotation/configuration/ConfigurationClassInheritanceTest.java @@ -0,0 +1,65 @@ +/* + * Copyright 2002-2013 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. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.context.annotation.configuration; + +import org.junit.Assert; +import org.junit.Test; +import org.springframework.beans.factory.config.BeanDefinition; +import org.springframework.context.annotation.AnnotationConfigApplicationContext; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.core.type.StandardMethodMetadata; + + +/** + * Test for SPR-10992. Check that bean definition is not overridden + * by superclass. + * + * @author Jose Luis Martin + */ +public class ConfigurationClassInheritanceTest { + + @Test + public void testBeanDefinitionOverriding() { + AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(Config.class); + BeanDefinition bd = ctx.getBeanDefinition("bean"); + StandardMethodMetadata metadata = (StandardMethodMetadata) bd.getSource(); + Assert.assertEquals(Config.class, metadata.getIntrospectedMethod().getDeclaringClass()); + ctx.close(); + } + + @Configuration + public static class ParentConfig { + + @Bean + public String bean() { + return "parentBean"; + } + } + + @Configuration + public static class Config extends ParentConfig { + + @Bean + public String bean() { + return "overridingBean"; + } + + } + +} +