zoukankan      html  css  js  c++  java
  • Java扫描classpath指定包路径下所有class

    在写框架时 经常需要扫描classpath指定包路径下带有某个Annotation的类,自己整理了一下 封装成一个工具类了,供大家参考。

    源代码
    ClassPathResourceScanner.java 如下:

    package com.bytebeats.jupiter.ioc;

    import com.bytebeats.jupiter.util.ClassHelper;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;

    import java.io.File;
    import java.io.IOException;
    import java.net.JarURLConnection;
    import java.net.URL;
    import java.net.URLDecoder;
    import java.util.*;
    import java.util.jar.JarEntry;
    import java.util.jar.JarFile;
    import java.util.regex.Pattern;

    /**
    * ${DESCRIPTION}
    *
    * @author Ricky Fung
    * @create 2016-12-11 16:02
    */
    public class ClassPathCandidateComponentScanner {
    private final Logger logger = LoggerFactory.getLogger(getClass());

    public static final String CLASS_SUFFIX = ".class";

    private static final Pattern INNER_PATTERN = java.util.regex.Pattern.compile("\$(\d+).", java.util.regex.Pattern.CASE_INSENSITIVE);

    public Set<Class<?>> findCandidateComponents(String packageName) throws IOException {
    if (packageName.endsWith(".")) {
    packageName = packageName.substring(0, packageName.length()-1);
    }
    Map<String, String> classMap = new HashMap<>(32);
    String path = packageName.replace(".", "/");
    Enumeration<URL> urls = findAllClassPathResources(path);
    while (urls!=null && urls.hasMoreElements()) {
    URL url = urls.nextElement();
    String protocol = url.getProtocol();
    if ("file".equals(protocol)) {
    String file = URLDecoder.decode(url.getFile(), "UTF-8");
    File dir = new File(file);
    if(dir.isDirectory()){
    parseClassFile(dir, packageName, classMap);
    }else {
    throw new IllegalArgumentException("file must be directory");
    }
    } else if ("jar".equals(protocol)) {
    parseJarFile(url, classMap);
    }
    }

    Set<Class<?>> set = new HashSet<>(classMap.size());
    for(String key : classMap.keySet()){
    String className = classMap.get(key);
    try {
    set.add(ClassHelper.forName(className));
    } catch (ClassNotFoundException e) {
    e.printStackTrace();
    }
    }
    return set;
    }

    protected void parseClassFile(File dir, String packageName, Map<String, String> classMap){
    if(dir.isDirectory()){
    File[] files = dir.listFiles();
    for (File file : files) {
    parseClassFile(file, packageName, classMap);
    }
    } else if(dir.getName().endsWith(CLASS_SUFFIX)) {
    String name = dir.getPath();
    name = name.substring(name.indexOf("classes")+8).replace("\", ".");
    System.out.println("file:"+dir+" class:"+name);
    addToClassMap(name, classMap);
    }
    }

    protected void parseJarFile(URL url, Map<String, String> classMap) throws IOException {
    JarFile jar = ((JarURLConnection) url.openConnection()).getJarFile();
    Enumeration<JarEntry> entries = jar.entries();
    while (entries.hasMoreElements()) {
    JarEntry entry = entries.nextElement();
    if (entry.isDirectory()) {
    continue;
    }
    String name = entry.getName();
    if(name.endsWith(CLASS_SUFFIX)){
    addToClassMap(name.replace("/", "."), classMap);
    }
    }
    }

    private boolean addToClassMap(String name, Map<String, String> classMap){

    if(INNER_PATTERN.matcher(name).find()){ //过滤掉匿名内部类
    System.out.println("anonymous inner class:"+name);
    return false;
    }
    System.out.println("class:"+name);
    if(name.indexOf("$")>0){ //内部类
    System.out.println("inner class:"+name);
    }
    if(!classMap.containsKey(name)){
    classMap.put(name, name.substring(0, name.length()-6)); //去掉.class
    }
    return true;
    }

    protected Enumeration<URL> findAllClassPathResources(String path) throws IOException {
    if(path.startsWith("/")){
    path = path.substring(1);
    }
    Enumeration<URL> urls = ClassHelper.getClassLoader().getResources(path);

    return urls;
    }

    }
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    使用方法
    ClassPathCandidateComponentScanner scanner = new ClassPathCandidateComponentScanner();
    //要扫描的包名
    String packageName = "com.bytebeats";
    //获取该包下所有的类名称
    Set<Class<?>> set = scanner.findCandidateComponents(packageName);
    System.out.println(set.size());
    for (Class<?> cls : set){
    System.out.println(cls.getName());
    }
    1
    2
    3
    4
    5
    6
    7
    8
    9

    这方面已经有一些不错的开源项目,例如:
    reflections:https://github.com/ronmamo/reflections
    Scannotation:http://scannotation.sourceforge.net/
    ---------------------
    作者:Ricky_Fung
    来源:CSDN
    原文:https://blog.csdn.net/top_code/article/details/53574523
    版权声明:本文为博主原创文章,转载请附上博文链接!

  • 相关阅读:
    CAS无锁模式
    Redis 字符串结构和常用命令
    Redis 链表结构 和 常用命令
    Redis hash结构 和常用命令
    Spring + Redis ( 简单使用)
    使用idea 搭建一个 SpringBoot + Mybatis + logback 的maven 项
    Java 208道面试题及部分答案
    面试相关知识点
    使用IDEA 搭建一个SpringBoot + Hibernate + Gradle
    Java相关知识点
  • 原文地址:https://www.cnblogs.com/hfultrastrong/p/9810202.html
Copyright © 2011-2022 走看看