Added ASPECTJ and REGEX constants to FilterType, along with a corresponding 'pattern' attribute on ComponentScan.Filter

Issue: SPR-10593
This commit is contained in:
Juergen Hoeller
2013-09-26 21:16:46 +02:00
parent 11d20e337d
commit f705ec1a46
7 changed files with 199 additions and 151 deletions

View File

@@ -42,9 +42,10 @@ import org.springframework.core.type.filter.TypeFilter;
* always registered, meaning that any attempt to disable them at the
* {@code @ComponentScan} level would be ignored.
*
* <p>See @{@link Configuration} Javadoc for usage examples.
* <p>See @{@link Configuration}'s javadoc for usage examples.
*
* @author Chris Beams
* @author Juergen Hoeller
* @since 3.1
* @see Configuration
*/
@@ -139,31 +140,33 @@ public @interface ComponentScan {
@Retention(RetentionPolicy.RUNTIME)
@Target({})
@interface Filter {
/**
* The type of filter to use.
* <p>Note that the filter types available are limited to those that may
* be expressed as a {@code Class} in the {@link #value()} attribute. This is
* in contrast to {@code <context:component-scan/>}, which allows for
* expression-based (i.e., string-based) filters such as AspectJ pointcuts.
* These filter types are intentionally not supported here, and not available
* in the {@link FilterType} enum.
* @see FilterType
*/
FilterType type() default FilterType.ANNOTATION;
/**
* The class or classes to use as the filter. In the case of
* {@link FilterType#ANNOTATION}, the class will be the annotation itself. In the
* case of {@link FilterType#ASSIGNABLE_TYPE}, the class will be the type that
* detected components should be assignable to. And in the case of
* {@link FilterType#CUSTOM}, the class will be an implementation of
* {@link FilterType#ANNOTATION}, the class will be the annotation itself.
* In the case of {@link FilterType#ASSIGNABLE_TYPE}, the class will be the
* type that detected components should be assignable to. And in the case
* of {@link FilterType#CUSTOM}, the class will be an implementation of
* {@link TypeFilter}.
* <p>When multiple classes are specified, OR logic is applied, e.g. "include
* types annotated with {@code @Foo} OR {@code @Bar}".
* <p>Specifying zero classes is permitted but will have no effect on component
* scanning.
*/
Class<?>[] value();
Class<?>[] value() default {};
/**
* The String pattern (or patterns) to use for the filter, as an alternative to
* specifying a Class {@link #value()}. In the case of {@link FilterType#ASPECTJ},
* this is an AspectJ type pattern expression; in case of {@link FilterType#REGEX},
* a regex pattern for the fully-qualified class names to match.
*/
String[] pattern() default {};
}
}

View File

@@ -20,6 +20,7 @@ import java.lang.annotation.Annotation;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.regex.Pattern;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.config.BeanDefinitionHolder;
@@ -30,7 +31,9 @@ import org.springframework.core.env.Environment;
import org.springframework.core.io.ResourceLoader;
import org.springframework.core.type.filter.AbstractTypeHierarchyTraversingFilter;
import org.springframework.core.type.filter.AnnotationTypeFilter;
import org.springframework.core.type.filter.AspectJTypeFilter;
import org.springframework.core.type.filter.AssignableTypeFilter;
import org.springframework.core.type.filter.RegexPatternTypeFilter;
import org.springframework.core.type.filter.TypeFilter;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
@@ -40,6 +43,7 @@ import org.springframework.util.StringUtils;
* Parser for the @{@link ComponentScan} annotation.
*
* @author Chris Beams
* @author Juergen Hoeller
* @since 3.1
* @see ClassPathBeanDefinitionScanner#scan(String...)
* @see ComponentScanBeanDefinitionParser
@@ -138,25 +142,37 @@ class ComponentScanAnnotationParser {
switch (filterType) {
case ANNOTATION:
Assert.isAssignable(Annotation.class, filterClass,
"An error occured when processing a @ComponentScan " +
"ANNOTATION type filter: ");
"An error occured while processing a @ComponentScan ANNOTATION type filter: ");
@SuppressWarnings("unchecked")
Class<Annotation> annoClass = (Class<Annotation>)filterClass;
typeFilters.add(new AnnotationTypeFilter(annoClass));
Class<Annotation> annotationType = (Class<Annotation>) filterClass;
typeFilters.add(new AnnotationTypeFilter(annotationType));
break;
case ASSIGNABLE_TYPE:
typeFilters.add(new AssignableTypeFilter(filterClass));
break;
case CUSTOM:
Assert.isAssignable(TypeFilter.class, filterClass,
"An error occured when processing a @ComponentScan " +
"CUSTOM type filter: ");
"An error occured while processing a @ComponentScan CUSTOM type filter: ");
typeFilters.add(BeanUtils.instantiateClass(filterClass, TypeFilter.class));
break;
default:
throw new IllegalArgumentException("unknown filter type " + filterType);
throw new IllegalArgumentException("Filter type not supported with Class value: " + filterType);
}
}
for (String expression : filterAttributes.getStringArray("pattern")) {
switch (filterType) {
case ASPECTJ:
typeFilters.add(new AspectJTypeFilter(expression, this.resourceLoader.getClassLoader()));
break;
case REGEX:
typeFilters.add(new RegexPatternTypeFilter(Pattern.compile(expression)));
break;
default:
throw new IllegalArgumentException("Filter type not supported with String pattern: " + filterType);
}
}
return typeFilters;
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2010 the original author or authors.
* 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.
@@ -16,9 +16,6 @@
package org.springframework.context.annotation;
import org.springframework.core.type.filter.AssignableTypeFilter;
/**
* Enumeration of the type filters that may be used in conjunction with
* {@link ComponentScan @ComponentScan}.
@@ -42,12 +39,24 @@ public enum FilterType {
/**
* Filter candidates assignable to a given type.
* @see AssignableTypeFilter
* @see org.springframework.core.type.filter.AssignableTypeFilter
*/
ASSIGNABLE_TYPE,
/**
* Filter candidates matching a given AspectJ type pattern expression.
* @see org.springframework.core.type.filter.AspectJTypeFilter
*/
ASPECTJ,
/**
* Filter candidates matching a given regex pattern.
* @see org.springframework.core.type.filter.RegexPatternTypeFilter
*/
REGEX,
/** Filter candidates using a given custom
* {@link org.springframework.core.type.filter.TypeFilter} implementation
* {@link org.springframework.core.type.filter.TypeFilter} implementation.
*/
CUSTOM