package com.test.scaner;import static org.slf4j.LoggerFactory.getLogger;import java.io.File;import java.io.IOException;import java.lang.annotation.Annotation;import java.net.URL;import java.util.ArrayList;import java.util.Arrays;import java.util.HashMap;import java.util.List;import java.util.Map;import java.util.Map.Entry;import org.apache.commons.lang3.StringUtils;import org.slf4j.Logger;import com.google.common.collect.Lists;import eu.infomas.annotation.AnnotationDetector;import eu.infomas.annotation.AnnotationDetector.Reporter;import eu.infomas.annotation.AnnotationDetector.TypeReporter;/** * * Created by linjinzhi on 2016/11/18 * */public class AnnotationScanUtils { private static final Logger log = getLogger(AnnotationScanUtils.class); private AnnotationScanUtils(){} private static List> supportAnnotationClasses = new ArrayList<>();//特定注解作用下的类类型列表 private static Map , Class > classesMap = null;//类类型-注解类型映射 /** * 初始化列表和Map * @param annotaionType 用户自定义注解类型. * @param supportAnnotationPackage 注解作用下的类所在包 */ private static void init(Class annotaionType, String supportAnnotationPackage) { if(StringUtils.isNotBlank(supportAnnotationPackage)){ String[] sitenameClazzArray = StringUtils.split(supportAnnotationPackage, ";"); classesMap = scan(annotaionType, sitenameClazzArray); for(Entry , Class > entry : classesMap.entrySet()) { supportAnnotationClasses.add(entry.getKey()); } } } /** * 得到特定包下的特定注解作用的Class * @param annotaionType 要求扫描的注解类型 * @param supportAnnotationPackage 扫描的包名称,如果有多个,则以';'分隔 * @return 被特定注解作用且位于制定包下的所有具体类类型列表 */ public static List > getSupportClasses(Class annotaionType, String supportAnnotationPackage) { init(annotaionType, supportAnnotationPackage); return supportAnnotationClasses; } /** * 得到类类型-注解类型映射 * @return */ public static Map , Class > getObjectAnnotationMap(Class annotaionType, String supportAnnotationPackage) { init(annotaionType, supportAnnotationPackage); return classesMap; } /** * 扫描类注解. * * @param annotationClass * @param packages * @return */ private static Map , Class > scan( final Class annotationClass, String... packages) { final Map , Class > classesMap = new HashMap<>(); final Reporter reporter = new TypeReporter() { @SuppressWarnings("unchecked") @Override public Class [] annotations() { return new Class[] { annotationClass }; } @Override public void reportTypeAnnotation( Class annotation, String className) { try { classesMap.put(Class.forName(className), annotation); } catch (ClassNotFoundException e) { log.error("Class not found: {}", className, e); } } }; startScan(reporter, packages); return classesMap; } private static void startScan( final AnnotationDetector.Reporter reporter, String... packageNames) { final AnnotationDetector cf = new AnnotationDetector(reporter); try { if (packageNames.length == 0) { // 解决在web容器下扫描不到类的问题. URL url = Thread.currentThread().getContextClassLoader() .getResource(""); File file = new File(url.getPath()); File[] files = file.listFiles( (File pathname) -> pathname.isDirectory() && !pathname.isHidden() ); List fileNames = Lists.newLinkedList(); for (File one : files) { fileNames.add(one.getName()); } log.debug("san path:{}", fileNames); cf.detect(fileNames.toArray(new String[fileNames.size()])); // 这里扫描全部可能会有性能问题 // XXX 在java项目中可以扫描到jar文件中的类,在web项目中不行. cf.detect(); } else { cf.detect(packageNames); } } catch (IOException e) { log.error("scan package error packages:{}", Arrays.toString(packageNames), e); } } /** * test * @param args */ public static void main(String[] args) { List > classes = AnnotationScanUtils.getSupportClasses(Crawler.class, "com.test.scaner;"); for(Class clazz : classes) { System.out.println(clazz); } Map , Class > map = AnnotationScanUtils.getObjectAnnotationMap(Crawler.class, "com.test.scaner;"); for(Entry , Class > entry : map.entrySet()) { System.out.println(entry.getKey()+"\t"+entry.getValue()); } }}