diff --git a/spring-context/src/main/java/org/springframework/context/annotation/ClassPathScanningCandidateComponentProvider.java b/spring-context/src/main/java/org/springframework/context/annotation/ClassPathScanningCandidateComponentProvider.java index 47137031b55..765b5caf77d 100644 --- a/spring-context/src/main/java/org/springframework/context/annotation/ClassPathScanningCandidateComponentProvider.java +++ b/spring-context/src/main/java/org/springframework/context/annotation/ClassPathScanningCandidateComponentProvider.java @@ -386,6 +386,7 @@ public class ClassPathScanningCandidateComponentProvider implements EnvironmentC MetadataReader metadataReader = getMetadataReaderFactory().getMetadataReader(type); if (isCandidateComponent(metadataReader)) { ScannedGenericBeanDefinition sbd = new ScannedGenericBeanDefinition(metadataReader); + sbd.setSource(metadataReader.getResource()); if (isCandidateComponent(sbd)) { if (debugEnabled) { logger.debug("Using candidate component class from index: " + type); @@ -428,7 +429,6 @@ public class ClassPathScanningCandidateComponentProvider implements EnvironmentC MetadataReader metadataReader = getMetadataReaderFactory().getMetadataReader(resource); if (isCandidateComponent(metadataReader)) { ScannedGenericBeanDefinition sbd = new ScannedGenericBeanDefinition(metadataReader); - sbd.setResource(resource); sbd.setSource(resource); if (isCandidateComponent(sbd)) { if (debugEnabled) { 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 ebda39c954e..5f884f6fb57 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-2019 the original author or authors. + * Copyright 2002-2020 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. @@ -212,7 +212,6 @@ class ConfigurationClassBeanDefinitionReader { } ConfigurationClassBeanDefinition beanDef = new ConfigurationClassBeanDefinition(configClass, metadata); - beanDef.setResource(configClass.getResource()); beanDef.setSource(this.sourceExtractor.extractSource(metadata, configClass.getResource())); if (metadata.isStatic()) { @@ -402,6 +401,7 @@ class ConfigurationClassBeanDefinitionReader { public ConfigurationClassBeanDefinition(ConfigurationClass configClass, MethodMetadata beanMethodMetadata) { this.annotationMetadata = configClass.getMetadata(); this.factoryMethodMetadata = beanMethodMetadata; + setResource(configClass.getResource()); setLenientConstructorResolution(false); } diff --git a/spring-context/src/main/java/org/springframework/context/annotation/ScannedGenericBeanDefinition.java b/spring-context/src/main/java/org/springframework/context/annotation/ScannedGenericBeanDefinition.java index 71174fd23d4..26e603bbf25 100644 --- a/spring-context/src/main/java/org/springframework/context/annotation/ScannedGenericBeanDefinition.java +++ b/spring-context/src/main/java/org/springframework/context/annotation/ScannedGenericBeanDefinition.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2014 the original author or authors. + * Copyright 2002-2020 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. @@ -60,6 +60,7 @@ public class ScannedGenericBeanDefinition extends GenericBeanDefinition implemen Assert.notNull(metadataReader, "MetadataReader must not be null"); this.metadata = metadataReader.getAnnotationMetadata(); setBeanClassName(this.metadata.getClassName()); + setResource(metadataReader.getResource()); } diff --git a/spring-context/src/test/java/org/springframework/context/annotation/ClassPathBeanDefinitionScannerTests.java b/spring-context/src/test/java/org/springframework/context/annotation/ClassPathBeanDefinitionScannerTests.java index 225a6fc7440..cfb389e6a46 100644 --- a/spring-context/src/test/java/org/springframework/context/annotation/ClassPathBeanDefinitionScannerTests.java +++ b/spring-context/src/test/java/org/springframework/context/annotation/ClassPathBeanDefinitionScannerTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2019 the original author or authors. + * Copyright 2002-2020 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. @@ -28,6 +28,7 @@ import org.springframework.beans.BeanInstantiationException; import org.springframework.beans.factory.BeanCreationException; import org.springframework.beans.factory.NoSuchBeanDefinitionException; import org.springframework.beans.factory.config.BeanDefinition; +import org.springframework.beans.factory.support.AbstractBeanDefinition; import org.springframework.beans.factory.support.BeanDefinitionRegistry; import org.springframework.beans.factory.support.RootBeanDefinition; import org.springframework.beans.factory.support.StaticListableBeanFactory; @@ -35,6 +36,8 @@ import org.springframework.beans.testfixture.beans.TestBean; import org.springframework.context.MessageSource; import org.springframework.context.annotation2.NamedStubDao2; import org.springframework.context.support.GenericApplicationContext; +import org.springframework.context.testfixture.index.CandidateComponentsTestClassLoader; +import org.springframework.core.io.ClassPathResource; import org.springframework.core.type.filter.AnnotationTypeFilter; import org.springframework.core.type.filter.AssignableTypeFilter; import org.springframework.stereotype.Component; @@ -104,10 +107,66 @@ public class ClassPathBeanDefinitionScannerTests { @Test public void testDoubleScan() { GenericApplicationContext context = new GenericApplicationContext(); + ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(context); int beanCount = scanner.scan(BASE_PACKAGE); assertThat(beanCount).isEqualTo(12); - scanner.scan(BASE_PACKAGE); + + ClassPathBeanDefinitionScanner scanner2 = new ClassPathBeanDefinitionScanner(context) { + @Override + protected void postProcessBeanDefinition(AbstractBeanDefinition beanDefinition, String beanName) { + super.postProcessBeanDefinition(beanDefinition, beanName); + beanDefinition.setAttribute("someDifference", "someValue"); + } + }; + scanner2.scan(BASE_PACKAGE); + + assertThat(context.containsBean("serviceInvocationCounter")).isTrue(); + assertThat(context.containsBean("fooServiceImpl")).isTrue(); + assertThat(context.containsBean("stubFooDao")).isTrue(); + assertThat(context.containsBean("myNamedComponent")).isTrue(); + assertThat(context.containsBean("myNamedDao")).isTrue(); + assertThat(context.containsBean("thoreau")).isTrue(); + } + + @Test + public void testWithIndex() { + GenericApplicationContext context = new GenericApplicationContext(); + context.setClassLoader(CandidateComponentsTestClassLoader.index( + ClassPathScanningCandidateComponentProviderTests.class.getClassLoader(), + new ClassPathResource("spring.components", FooServiceImpl.class))); + + ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(context); + int beanCount = scanner.scan(BASE_PACKAGE); + assertThat(beanCount).isEqualTo(12); + + assertThat(context.containsBean("serviceInvocationCounter")).isTrue(); + assertThat(context.containsBean("fooServiceImpl")).isTrue(); + assertThat(context.containsBean("stubFooDao")).isTrue(); + assertThat(context.containsBean("myNamedComponent")).isTrue(); + assertThat(context.containsBean("myNamedDao")).isTrue(); + assertThat(context.containsBean("thoreau")).isTrue(); + } + + @Test + public void testDoubleScanWithIndex() { + GenericApplicationContext context = new GenericApplicationContext(); + context.setClassLoader(CandidateComponentsTestClassLoader.index( + ClassPathScanningCandidateComponentProviderTests.class.getClassLoader(), + new ClassPathResource("spring.components", FooServiceImpl.class))); + + ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(context); + int beanCount = scanner.scan(BASE_PACKAGE); + assertThat(beanCount).isEqualTo(12); + + ClassPathBeanDefinitionScanner scanner2 = new ClassPathBeanDefinitionScanner(context) { + @Override + protected void postProcessBeanDefinition(AbstractBeanDefinition beanDefinition, String beanName) { + super.postProcessBeanDefinition(beanDefinition, beanName); + beanDefinition.setAttribute("someDifference", "someValue"); + } + }; + scanner2.scan(BASE_PACKAGE); assertThat(context.containsBean("serviceInvocationCounter")).isTrue(); assertThat(context.containsBean("fooServiceImpl")).isTrue();