参考mybatis MapperScannerConfigurer.java
最终找到 Spring的一个类 ClassPathBeanDefinitionScanner.java
参考ClassPathBeanDefinitionScanner 和它的父类 ClassPathScanningCandidateComponentProvider,将一些代码进行抽取,得到如下工具类。
import org.apache.commons.lang3.ArrayUtils; import org.springframework.beans.factory.BeanDefinitionStoreException; import org.springframework.context.ResourceLoaderAware; import org.springframework.core.io.Resource; import org.springframework.core.io.ResourceLoader; import org.springframework.core.io.support.PathMatchingResourcePatternResolver; import org.springframework.core.io.support.ResourcePatternResolver; import org.springframework.core.io.support.ResourcePatternUtils; import org.springframework.core.type.classreading.CachingMetadataReaderFactory; import org.springframework.core.type.classreading.MetadataReader; import org.springframework.core.type.classreading.MetadataReaderFactory; import org.springframework.core.type.filter.AnnotationTypeFilter; import org.springframework.core.type.filter.TypeFilter; import org.springframework.util.StringUtils; import org.springframework.util.SystemPropertyUtils;import java.io.IOException; import java.lang.annotation.Annotation; import java.util.HashSet; import java.util.LinkedList; import java.util.List; import java.util.Set;public class ClassScaner implements ResourceLoaderAware {//保存过滤规则要排除的注解private final List<TypeFilter> includeFilters = new LinkedList<TypeFilter>();private final List<TypeFilter> excludeFilters = new LinkedList<TypeFilter>();private ResourcePatternResolver resourcePatternResolver = new PathMatchingResourcePatternResolver();private MetadataReaderFactory metadataReaderFactory = new CachingMetadataReaderFactory(this.resourcePatternResolver);public static Set<Class> scan(String[] basePackages,Class<? extends Annotation>... annotations) {ClassScaner cs = new ClassScaner();if(ArrayUtils.isNotEmpty(annotations)) {for (Class anno : annotations) {cs.addIncludeFilter(new AnnotationTypeFilter(anno));}}Set<Class> classes = new HashSet<Class>();for (String s : basePackages)classes.addAll(cs.doScan(s));return classes;}public static Set<Class> scan(String basePackages, Class<? extends Annotation>... annotations) {return ClassScaner.scan(StringUtils.tokenizeToStringArray(basePackages, ",; \t\n"), annotations);}public final ResourceLoader getResourceLoader() {return this.resourcePatternResolver;}public void setResourceLoader(ResourceLoader resourceLoader) {this.resourcePatternResolver = ResourcePatternUtils.getResourcePatternResolver(resourceLoader);this.metadataReaderFactory = new CachingMetadataReaderFactory(resourceLoader);}public void addIncludeFilter(TypeFilter includeFilter) {this.includeFilters.add(includeFilter);}public void addExcludeFilter(TypeFilter excludeFilter) {this.excludeFilters.add(0, excludeFilter);}public void resetFilters(boolean useDefaultFilters) {this.includeFilters.clear();this.excludeFilters.clear();}public Set<Class> doScan(String basePackage) {Set<Class> classes = new HashSet<Class>();try {String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX+ org.springframework.util.ClassUtils.convertClassNameToResourcePath(SystemPropertyUtils.resolvePlaceholders(basePackage))+ "/**/*.class";Resource[] resources = this.resourcePatternResolver.getResources(packageSearchPath);for (int i = 0; i < resources.length; i++) {Resource resource = resources[i];if (resource.isReadable()) {MetadataReader metadataReader = this.metadataReaderFactory.getMetadataReader(resource);if ((includeFilters.size() == 0 && excludeFilters.size() == 0)|| matches(metadataReader)) {try {classes.add(Class.forName(metadataReader.getClassMetadata().getClassName()));} catch (ClassNotFoundException e) {e.printStackTrace();}}}}} catch (IOException ex) {throw new BeanDefinitionStoreException("I/O failure during classpath scanning", ex);}return classes;}protected boolean matches(MetadataReader metadataReader) throws IOException {for (TypeFilter tf : this.excludeFilters) {if (tf.match(metadataReader, this.metadataReaderFactory)) {return false;}}for (TypeFilter tf : this.includeFilters) {if (tf.match(metadataReader, this.metadataReaderFactory)) {return true;}}return false;}public static void main(String[] args) {ClassScaner.scan("com.hjzgg.test.thirdjar.config,com.hjzgg.test.thirdjar.web", null).forEach(clazz -> System.out.println(clazz));} }