From c8b6233bd03d43c8a91ec197e9cf1ea15bba478c Mon Sep 17 00:00:00 2001 From: Juergen Hoeller Date: Wed, 2 May 2018 15:20:42 +0200 Subject: [PATCH] Introspect originating bean definition as configuration class candidate Issue: SPR-16756 --- ...onfigurationClassBeanDefinitionReader.java | 7 +-- .../annotation/ConfigurationClassParser.java | 9 ++-- .../annotation/ConfigurationClassUtils.java | 6 +-- .../annotation/spr16756/ScannedComponent.java | 50 +++++++++++++++++++ .../spr16756/ScanningConfiguration.java | 24 +++++++++ .../annotation/spr16756/Spr16756Tests.java | 37 ++++++++++++++ 6 files changed, 124 insertions(+), 9 deletions(-) create mode 100644 spring-context/src/test/java/org/springframework/context/annotation/spr16756/ScannedComponent.java create mode 100644 spring-context/src/test/java/org/springframework/context/annotation/spr16756/ScanningConfiguration.java create mode 100644 spring-context/src/test/java/org/springframework/context/annotation/spr16756/Spr16756Tests.java 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 57a5ffa146..357b6ec579 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 @@ -1,5 +1,5 @@ /* - * Copyright 2002-2017 the original author or authors. + * Copyright 2002-2018 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. @@ -122,8 +122,8 @@ class ConfigurationClassBeanDefinitionReader { * Read a particular {@link ConfigurationClass}, registering bean definitions * for the class itself and all of its {@link Bean} methods. */ - private void loadBeanDefinitionsForConfigurationClass(ConfigurationClass configClass, - TrackedConditionEvaluator trackedConditionEvaluator) { + private void loadBeanDefinitionsForConfigurationClass( + ConfigurationClass configClass, TrackedConditionEvaluator trackedConditionEvaluator) { if (trackedConditionEvaluator.shouldSkip(configClass)) { String beanName = configClass.getBeanName(); @@ -140,6 +140,7 @@ class ConfigurationClassBeanDefinitionReader { for (BeanMethod beanMethod : configClass.getBeanMethods()) { loadBeanDefinitionsForBeanMethod(beanMethod); } + loadBeanDefinitionsFromImportedResources(configClass.getImportedResources()); loadBeanDefinitionsFromRegistrars(configClass.getImportBeanDefinitionRegistrars()); } diff --git a/spring-context/src/main/java/org/springframework/context/annotation/ConfigurationClassParser.java b/spring-context/src/main/java/org/springframework/context/annotation/ConfigurationClassParser.java index 2d3bb969dc..b8eb4f96b3 100644 --- a/spring-context/src/main/java/org/springframework/context/annotation/ConfigurationClassParser.java +++ b/spring-context/src/main/java/org/springframework/context/annotation/ConfigurationClassParser.java @@ -288,9 +288,12 @@ class ConfigurationClassParser { this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName()); // Check the set of scanned definitions for any further config classes and parse recursively if needed for (BeanDefinitionHolder holder : scannedBeanDefinitions) { - if (ConfigurationClassUtils.checkConfigurationClassCandidate( - holder.getBeanDefinition(), this.metadataReaderFactory)) { - parse(holder.getBeanDefinition().getBeanClassName(), holder.getBeanName()); + BeanDefinition bdCand = holder.getBeanDefinition().getOriginatingBeanDefinition(); + if (bdCand == null) { + bdCand = holder.getBeanDefinition(); + } + if (ConfigurationClassUtils.checkConfigurationClassCandidate(bdCand, this.metadataReaderFactory)) { + parse(bdCand.getBeanClassName(), holder.getBeanName()); } } } diff --git a/spring-context/src/main/java/org/springframework/context/annotation/ConfigurationClassUtils.java b/spring-context/src/main/java/org/springframework/context/annotation/ConfigurationClassUtils.java index bb89e3da3c..4d579f653a 100644 --- a/spring-context/src/main/java/org/springframework/context/annotation/ConfigurationClassUtils.java +++ b/spring-context/src/main/java/org/springframework/context/annotation/ConfigurationClassUtils.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2017 the original author or authors. + * Copyright 2002-2018 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. @@ -39,7 +39,7 @@ import org.springframework.lang.Nullable; import org.springframework.stereotype.Component; /** - * Utilities for processing @{@link Configuration} classes. + * Utilities for identifying @{@link Configuration} classes. * * @author Chris Beams * @author Juergen Hoeller @@ -60,7 +60,7 @@ abstract class ConfigurationClassUtils { private static final Log logger = LogFactory.getLog(ConfigurationClassUtils.class); - private static final Set candidateIndicators = new HashSet<>(4); + private static final Set candidateIndicators = new HashSet<>(8); static { candidateIndicators.add(Component.class.getName()); diff --git a/spring-context/src/test/java/org/springframework/context/annotation/spr16756/ScannedComponent.java b/spring-context/src/test/java/org/springframework/context/annotation/spr16756/ScannedComponent.java new file mode 100644 index 0000000000..c716927fdf --- /dev/null +++ b/spring-context/src/test/java/org/springframework/context/annotation/spr16756/ScannedComponent.java @@ -0,0 +1,50 @@ +/* + * Copyright 2002-2018 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.spr16756; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Scope; +import org.springframework.context.annotation.ScopedProxyMode; +import org.springframework.stereotype.Component; + +@Component +public class ScannedComponent { + + @Autowired + private State state; + + public String iDoAnything() { + return state.anyMethod(); + } + + + public interface State { + + String anyMethod(); + } + + + @Component + @Scope(proxyMode = ScopedProxyMode.INTERFACES, value = "prototype") + public static class StateImpl implements State { + + public String anyMethod() { + return "anyMethod called"; + } + } + +} diff --git a/spring-context/src/test/java/org/springframework/context/annotation/spr16756/ScanningConfiguration.java b/spring-context/src/test/java/org/springframework/context/annotation/spr16756/ScanningConfiguration.java new file mode 100644 index 0000000000..9f0f73b681 --- /dev/null +++ b/spring-context/src/test/java/org/springframework/context/annotation/spr16756/ScanningConfiguration.java @@ -0,0 +1,24 @@ +/* + * Copyright 2002-2018 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.spr16756; + +import org.springframework.context.annotation.ComponentScan; + +@ComponentScan +public class ScanningConfiguration { + +} diff --git a/spring-context/src/test/java/org/springframework/context/annotation/spr16756/Spr16756Tests.java b/spring-context/src/test/java/org/springframework/context/annotation/spr16756/Spr16756Tests.java new file mode 100644 index 0000000000..c9cf2f7001 --- /dev/null +++ b/spring-context/src/test/java/org/springframework/context/annotation/spr16756/Spr16756Tests.java @@ -0,0 +1,37 @@ +/* + * Copyright 2002-2018 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.spr16756; + +import org.junit.Test; + +import org.springframework.context.annotation.AnnotationConfigApplicationContext; + +/** + * @author Juergen Hoeller + */ +public class Spr16756Tests { + + @Test + public void shouldNotFailOnNestedScopedComponent() { + AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(); + context.register(ScanningConfiguration.class); + context.refresh(); + context.getBean(ScannedComponent.class); + context.getBean(ScannedComponent.State.class); + } + +}