zoukankan      html  css  js  c++  java
  • 获取指定接口的所有实现类或获取指定类的所有继承类

    看Spring时,注意到有类实现了WebApplicationInitializer接口的方式来增加监听、过滤器的功能,跟之前通过配置web.xml的方式完全不同。但在这个实现类上又没有找到Spring的注解等入口,所以很好奇,这个实现类是怎么走进来的。
    百度了一下,原来可以通过某个接口获取它的所有实现类的功能,于是记录下来,方便后面使用。大概原理为:遍历所有的相关类,通过
    clazz.isAssignableFrom(allClass.get(i))方法来判断是不是实现了某接口。

    具体代码如下:



    package pri.lime.main; import java.io.File; import java.io.IOException; import java.net.URL; import java.util.ArrayList; import java.util.Enumeration;
    /** * 查找指定路径下面实现指定接口的全部类 * * @author Liang * * 2017年5月9日 */ public class ClassUtil { @SuppressWarnings({ "rawtypes", "unchecked" }) public static ArrayList<Class> getAllClassByInterface(Class clazz) { ArrayList<Class> list = new ArrayList<>(); // 判断是否是一个接口 if (clazz.isInterface()) { try { ArrayList<Class> allClass = getAllClass(clazz.getPackage().getName()); /** * 循环判断路径下的所有类是否实现了指定的接口 并且排除接口类自己 */ for (int i = 0; i < allClass.size(); i++) { /** * 判断是不是同一个接口 */ // isAssignableFrom:判定此 Class 对象所表示的类或接口与指定的 Class // 参数所表示的类或接口是否相同,或是否是其超类或超接口 if (clazz.isAssignableFrom(allClass.get(i))) { if (!clazz.equals(allClass.get(i))) { // 自身并不加进去 list.add(allClass.get(i)); } } } } catch (Exception e) { System.out.println("出现异常"); } } else { // 如果不是接口,则获取它的所有子类 try { ArrayList<Class> allClass = getAllClass(clazz.getPackage().getName()); /** * 循环判断路径下的所有类是否继承了指定类 并且排除父类自己 */ for (int i = 0; i < allClass.size(); i++) { if (clazz.isAssignableFrom(allClass.get(i))) { if (!clazz.equals(allClass.get(i))) { // 自身并不加进去 list.add(allClass.get(i)); } } } } catch (Exception e) { System.out.println("出现异常"); } } return list; } /** * 从一个指定路径下查找所有的类 * * @param name */ @SuppressWarnings("rawtypes") private static ArrayList<Class> getAllClass(String packagename) { ArrayList<Class> list = new ArrayList<>(); // 返回对当前正在执行的线程对象的引用。 // 返回该线程的上下文 ClassLoader。 ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); String path = packagename.replace('.', '/'); try { ArrayList<File> fileList = new ArrayList<>(); /** * 这里面的路径使用的是相对路径 如果大家在测试的时候获取不到,请理清目前工程所在的路径 使用相对路径更加稳定! * 另外,路径中切不可包含空格、特殊字符等! */ // getResources:查找所有给定名称的资源 // 获取jar包中的实现类:Enumeration<URL> enumeration = // classLoader.getResources(path); Enumeration<URL> enumeration = classLoader.getResources("../bin/" + path); while (enumeration.hasMoreElements()) { URL url = enumeration.nextElement(); // 获取此 URL 的文件名 fileList.add(new File(url.getFile())); } for (int i = 0; i < fileList.size(); i++) { list.addAll(findClass(fileList.get(i), packagename)); } } catch (IOException e) { e.printStackTrace(); } return list; } /** * 如果file是文件夹,则递归调用findClass方法,或者文件夹下的类 如果file本身是类文件,则加入list中进行保存,并返回 * * @param file * @param packagename * @return */ @SuppressWarnings("rawtypes") private static ArrayList<Class> findClass(File file, String packagename) { ArrayList<Class> list = new ArrayList<>(); if (!file.exists()) { return list; } // 返回一个抽象路径名数组,这些路径名表示此抽象路径名表示的目录中的文件。 File[] files = file.listFiles(); for (File file2 : files) { if (file2.isDirectory()) { // assert !file2.getName().contains(".");// 添加断言用于判断 if (!file2.getName().contains(".")) { ArrayList<Class> arrayList = findClass(file2, packagename + "." + file2.getName()); list.addAll(arrayList); } } else if (file2.getName().endsWith(".class")) { try { // 保存的类文件不需要后缀.class list.add(Class.forName(packagename + '.' + file2.getName().substring(0, file2.getName().length() - 6))); } catch (ClassNotFoundException e) { e.printStackTrace(); } } } return list; } }
  • 相关阅读:
    题目3:爬楼梯
    题目1:删除排序数组中的重复数字
    最近目标
    软件工程----个人总结
    软件工程第二次作业——结对编程
    软件工程第一次作业补充
    爬楼梯
    买卖股票的最佳时机
    删除排序数组中的重复数字
    思考题
  • 原文地址:https://www.cnblogs.com/aligege/p/7977087.html
Copyright © 2011-2022 走看看