diff --git a/spring-context/src/main/java/org/springframework/context/annotation/ComponentScanBeanDefinitionParser.java b/spring-context/src/main/java/org/springframework/context/annotation/ComponentScanBeanDefinitionParser.java index 3a4bf809b0c..26bf6849e91 100644 --- a/spring-context/src/main/java/org/springframework/context/annotation/ComponentScanBeanDefinitionParser.java +++ b/spring-context/src/main/java/org/springframework/context/annotation/ComponentScanBeanDefinitionParser.java @@ -77,7 +77,9 @@ public class ComponentScanBeanDefinitionParser implements BeanDefinitionParser { @Override public BeanDefinition parse(Element element, ParserContext parserContext) { - String[] basePackages = StringUtils.tokenizeToStringArray(element.getAttribute(BASE_PACKAGE_ATTRIBUTE), + String basePackage = element.getAttribute(BASE_PACKAGE_ATTRIBUTE); + basePackage = parserContext.getReaderContext().getEnvironment().resolvePlaceholders(basePackage); + String[] basePackages = StringUtils.tokenizeToStringArray(basePackage, ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS); // Actually scan for bean definitions and register them. @@ -89,17 +91,15 @@ public class ComponentScanBeanDefinitionParser implements BeanDefinitionParser { } protected ClassPathBeanDefinitionScanner configureScanner(ParserContext parserContext, Element element) { - XmlReaderContext readerContext = parserContext.getReaderContext(); - boolean useDefaultFilters = true; if (element.hasAttribute(USE_DEFAULT_FILTERS_ATTRIBUTE)) { useDefaultFilters = Boolean.valueOf(element.getAttribute(USE_DEFAULT_FILTERS_ATTRIBUTE)); } // Delegate bean definition registration to scanner class. - ClassPathBeanDefinitionScanner scanner = createScanner(readerContext, useDefaultFilters); - scanner.setResourceLoader(readerContext.getResourceLoader()); - scanner.setEnvironment(parserContext.getDelegate().getEnvironment()); + ClassPathBeanDefinitionScanner scanner = createScanner(parserContext.getReaderContext(), useDefaultFilters); + scanner.setResourceLoader(parserContext.getReaderContext().getResourceLoader()); + scanner.setEnvironment(parserContext.getReaderContext().getEnvironment()); scanner.setBeanDefinitionDefaults(parserContext.getDelegate().getBeanDefinitionDefaults()); scanner.setAutowireCandidatePatterns(parserContext.getDelegate().getAutowireCandidatePatterns()); @@ -111,17 +111,17 @@ public class ComponentScanBeanDefinitionParser implements BeanDefinitionParser { parseBeanNameGenerator(element, scanner); } catch (Exception ex) { - readerContext.error(ex.getMessage(), readerContext.extractSource(element), ex.getCause()); + parserContext.getReaderContext().error(ex.getMessage(), parserContext.extractSource(element), ex.getCause()); } try { parseScope(element, scanner); } catch (Exception ex) { - readerContext.error(ex.getMessage(), readerContext.extractSource(element), ex.getCause()); + parserContext.getReaderContext().error(ex.getMessage(), parserContext.extractSource(element), ex.getCause()); } - parseTypeFilters(element, scanner, readerContext, parserContext); + parseTypeFilters(element, scanner, parserContext); return scanner; } @@ -195,9 +195,7 @@ public class ComponentScanBeanDefinitionParser implements BeanDefinitionParser { } } - protected void parseTypeFilters( - Element element, ClassPathBeanDefinitionScanner scanner, XmlReaderContext readerContext, ParserContext parserContext) { - + protected void parseTypeFilters(Element element, ClassPathBeanDefinitionScanner scanner, ParserContext parserContext) { // Parse exclude and include filter elements. ClassLoader classLoader = scanner.getResourceLoader().getClassLoader(); NodeList nodeList = element.getChildNodes(); @@ -207,25 +205,27 @@ public class ComponentScanBeanDefinitionParser implements BeanDefinitionParser { String localName = parserContext.getDelegate().getLocalName(node); try { if (INCLUDE_FILTER_ELEMENT.equals(localName)) { - TypeFilter typeFilter = createTypeFilter((Element) node, classLoader); + TypeFilter typeFilter = createTypeFilter((Element) node, classLoader, parserContext); scanner.addIncludeFilter(typeFilter); } else if (EXCLUDE_FILTER_ELEMENT.equals(localName)) { - TypeFilter typeFilter = createTypeFilter((Element) node, classLoader); + TypeFilter typeFilter = createTypeFilter((Element) node, classLoader, parserContext); scanner.addExcludeFilter(typeFilter); } } catch (Exception ex) { - readerContext.error(ex.getMessage(), readerContext.extractSource(element), ex.getCause()); + parserContext.getReaderContext().error( + ex.getMessage(), parserContext.extractSource(element), ex.getCause()); } } } } @SuppressWarnings("unchecked") - protected TypeFilter createTypeFilter(Element element, ClassLoader classLoader) { + protected TypeFilter createTypeFilter(Element element, ClassLoader classLoader, ParserContext parserContext) { String filterType = element.getAttribute(FILTER_TYPE_ATTRIBUTE); String expression = element.getAttribute(FILTER_EXPRESSION_ATTRIBUTE); + expression = parserContext.getReaderContext().getEnvironment().resolvePlaceholders(expression); try { if ("annotation".equals(filterType)) { return new AnnotationTypeFilter((Class) classLoader.loadClass(expression)); diff --git a/spring-context/src/test/java/org/springframework/context/annotation/ComponentScanParserTests.java b/spring-context/src/test/java/org/springframework/context/annotation/ComponentScanParserTests.java index 8208b490b9d..9298ad6caf0 100644 --- a/spring-context/src/test/java/org/springframework/context/annotation/ComponentScanParserTests.java +++ b/spring-context/src/test/java/org/springframework/context/annotation/ComponentScanParserTests.java @@ -32,7 +32,6 @@ import org.springframework.context.support.GenericXmlApplicationContext; import org.springframework.core.type.classreading.MetadataReader; import org.springframework.core.type.classreading.MetadataReaderFactory; import org.springframework.core.type.filter.TypeFilter; -import org.springframework.stereotype.Component; import static org.hamcrest.CoreMatchers.*; import static org.junit.Assert.*; @@ -49,8 +48,9 @@ public class ComponentScanParserTests { return new ClassPathXmlApplicationContext(path, getClass()); } + @Test - public void aspectJTypeFilter() { + public void aspectjTypeFilter() { ClassPathXmlApplicationContext context = loadContext("aspectjTypeFilterTests.xml"); assertTrue(context.containsBean("fooServiceImpl")); assertTrue(context.containsBean("stubFooDao")); @@ -58,6 +58,25 @@ public class ComponentScanParserTests { context.close(); } + @Test + public void aspectjTypeFilterWithPlaceholders() { + System.setProperty("basePackage", "example.scannable, test"); + System.setProperty("scanInclude", "example.scannable.FooService+"); + System.setProperty("scanExclude", "example..Scoped*Test*"); + try { + ClassPathXmlApplicationContext context = loadContext("aspectjTypeFilterTestsWithPlaceholders.xml"); + assertTrue(context.containsBean("fooServiceImpl")); + assertTrue(context.containsBean("stubFooDao")); + assertFalse(context.containsBean("scopedProxyTestBean")); + context.close(); + } + finally { + System.clearProperty("basePackage"); + System.clearProperty("scanInclude"); + System.clearProperty("scanExclude"); + } + } + @Test public void nonMatchingResourcePattern() { ClassPathXmlApplicationContext context = loadContext("nonMatchingResourcePatternTests.xml"); @@ -131,6 +150,7 @@ public class ComponentScanParserTests { public static @interface CustomAnnotation { } + /** * Intentionally spelling "custom" with a "k" since there are numerous * classes in this package named *Custom*. @@ -146,6 +166,7 @@ public class ComponentScanParserTests { } } + /** * Intentionally spelling "custom" with a "k" since there are numerous * classes in this package named *Custom*. @@ -154,6 +175,7 @@ public class ComponentScanParserTests { public static class KustomAnnotationDependencyBean { } + public static class CustomTypeFilter implements TypeFilter { /** diff --git a/spring-context/src/test/java/org/springframework/context/annotation/aspectjTypeFilterTests.xml b/spring-context/src/test/java/org/springframework/context/annotation/aspectjTypeFilterTests.xml index e3521020483..5dcd6ad62af 100644 --- a/spring-context/src/test/java/org/springframework/context/annotation/aspectjTypeFilterTests.xml +++ b/spring-context/src/test/java/org/springframework/context/annotation/aspectjTypeFilterTests.xml @@ -8,7 +8,7 @@ - + diff --git a/spring-context/src/test/java/org/springframework/context/annotation/aspectjTypeFilterTestsWithPlaceholders.xml b/spring-context/src/test/java/org/springframework/context/annotation/aspectjTypeFilterTestsWithPlaceholders.xml new file mode 100644 index 00000000000..362bcdce344 --- /dev/null +++ b/spring-context/src/test/java/org/springframework/context/annotation/aspectjTypeFilterTestsWithPlaceholders.xml @@ -0,0 +1,14 @@ + + + + + + + + + +