Java扫包工具类
自定义Scanner工具类,用于扫包获取Class对象,
- 根据包名获取所有的class对象。
- 根据包名和指定注解的class,获取该包下所有含有该注解的class对象。
- 根据包名和指定的接口的class,获取该包下所有实现该接口的class对象。
- 使用了Map作为本地缓存,对于同一个包名不会重复读取IO资源。
package com.wang.mygateway.serviceportal.utils;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.type.classreading.CachingMetadataReaderFactory;
import org.springframework.core.type.classreading.MetadataReader;
import org.springframework.util.ClassUtils;
import java.lang.annotation.Annotation;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;
public class Scanner {
private static final String RESOURCE_PATTERN = "/**/*.class";
private static final Map<String,Set<Class<?>>> cacheMap = new ConcurrentHashMap();
public Scanner(){
}
/**
* 获取某个包下所有的class对象
* @param packageName
* @return
*/
public static Set<Class<?>> getClasses(String packageName){
Set<Class<?>> cacheSet = cacheMap.get(packageName);
if (cacheSet!=null){
return cacheSet;
}
cacheSet = new HashSet<>();
cacheMap.put(packageName,cacheSet);
Set<Class<?>> handlerSet = new HashSet();
PathMatchingResourcePatternResolver resourcePatternResolver = new PathMatchingResourcePatternResolver();
try{
String pattern = "classpath*:"+ ClassUtils.convertClassNameToResourcePath(packageName)+RESOURCE_PATTERN;
Resource[] resources = resourcePatternResolver.getResources(pattern);
CachingMetadataReaderFactory readerFactory = new CachingMetadataReaderFactory(resourcePatternResolver);
Resource[] var1 = resources;
int var2 = resources.length;
for (int var3 = 0; var3 < var2; ++var3){
Resource resource = var1[var3];
try{
MetadataReader reader = readerFactory.getMetadataReader(resource);
String className = reader.getClassMetadata().getClassName();
Class<?> clazz = Class.forName(className);
handlerSet.add(clazz);
}catch (Exception e){
e.printStackTrace();
}
}
}catch (Exception e){
e.printStackTrace();
}
cacheSet.addAll(handlerSet);
return handlerSet;
}
public static Set<Class<?>> getClassesByAnnotation(String packageName,Class<? extends Annotation> cls){
return getClassesByAnnotation(packageName,cls,true);
}
/**
* 获取某个包下,含有指定注解的class对象
* @param packageName
* @param cls 指定注解
* @param all 是否获取全部,false时只获取第一个
* @return
*/
public static Set<Class<?>> getClassesByAnnotation(String packageName,Class<? extends Annotation> cls,boolean all){
Set<Class<?>> classes = getClasses(packageName);
Set<Class<?>> list = classes.stream().filter(clazz -> {
Annotation annotation = clazz.getAnnotation(cls);
return annotation != null;
}).collect(Collectors.toSet());
if (!all){
return list.stream().limit(1).collect(Collectors.toSet());
}else{
return list;
}
}
public static Set<Class<?>> getClassesByInterface(String packageName,Class cls){
return getClassesByInterface(packageName,cls,true);
}
/**
* 获取某个包下,实现指定接口的class对象。
* @param packageName
* @param cls 指定接口
* @param all 是否获取全部
* @return
*/
public static Set<Class<?>> getClassesByInterface(String packageName,Class cls,boolean all){
Set<Class<?>> classes = getClasses(packageName);
Set<Class<?>> list = classes.stream().filter(clazz -> {
Class<?>[] interfaces = clazz.getInterfaces();
for (Class<?> anInterface : interfaces) {
if (anInterface.equals(cls)){
return true;
}
}
return false;
}).collect(Collectors.toSet());
if (!all){
return list.stream().limit(1).collect(Collectors.toSet());
}else{
return list;
}
}
}