JAVA使用反射动态的获取接口的所有实现类(通过接口类路径)

    

    /**
     * 测试
     * @param args
     */
    public static void main(String[] args) {
        List<接口名> list = new ArrayList<>();
        List<Class> clazzs = getAllInterfaceAchieveClass(接口名.class);
        for(Class clazz : clazzs){
            list.add((接口名)clazz.newInstance());
        }
        //打印Class对象
        for(接口名 cla : list){
            System.out.println("实现类:"+cla.getClass());
        }
    }

/**
     * 获取所有接口的实现类
     * 
     * @return
     * @throws Throwable
     */
    @SuppressWarnings("unchecked")
    public List<Class> getAllInterfaceAchieveClass(Class clazz) throws Throwable {
        ArrayList<Class> list = new ArrayList<>();
        // 判断是否是接口
        if (clazz.isInterface()) {
            ArrayList<Class> allClass = getAllClassByPath(clazz.getPackage().getName());
            /**
             * 循环判断路径下的所有类是否实现了指定的接口 并且排除接口类自己
             */
            for (int i = 0; i < allClass.size(); i++) {
                // 排除抽象类
                if (Modifier.isAbstract(allClass.get(i).getModifiers())) {
                    continue;
                }
                // 判断是不是同一个接口
                if (clazz.isAssignableFrom(allClass.get(i))) {
                    if (!clazz.equals(allClass.get(i))) {
                        list.add(allClass.get(i));
                    }
                }
            }
        }
        return list;
    }

    /**
     * 从指定路径下获取所有类
     * 
     * @return
     * @throws Throwable
     */
    public ArrayList<Class> getAllClassByPath(String packagename) throws Throwable {
        ArrayList<Class> list = new ArrayList<>();
        ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
        String path = packagename.replace('.', '/');
        ArrayList<File> fileList = new ArrayList<>();
        Enumeration<URL> enumeration = classLoader.getResources(path);
        while (enumeration.hasMoreElements()) {
            URL url = enumeration.nextElement();
            fileList.add(new File(url.getFile()));
        }
        for (int i = 0; i < fileList.size(); i++) {
            list.addAll(findClass(fileList.get(i), packagename));
        }
        return list;
    }

    /**
     * 如果file是文件夹,则递归调用findClass方法,或者文件夹下的类 如果file本身是类文件,则加入list中进行保存,并返回
     * 
     * @param file
     * @param packagename
     * @return
     * @throws ClassNotFoundException
     */
    private ArrayList<Class> findClass(File file, String packagename) throws ClassNotFoundException {
        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(".");// 添加断言用于判断
                ArrayList<Class> arrayList = findClass(file2, packagename + "." + file2.getName());
                list.addAll(arrayList);
            } else if (file2.getName().endsWith(".class")) {
                // 保存的类文件不需要后缀.class
                list.add(Class.forName(packagename + '.' + file2.getName().substring(0, file2.getName().length() - 6)));
            }
        }
        return list;
    }

 jar里找到包下所有实现类

    /**
     * 测试
     * @param args
     */
    public static void main(String[] args) {
        List<接口名> list = new ArrayList<>();
        List<Class> clazzs = getClasses(接口名.class);
        for(Class clazz : clazzs){
            list.add((接口名)clazz.newInstance());
        }
        //打印Class对象
        for(接口名 cla : list){
            System.out.println("实现类:"+cla.getClass());
        }
    }


	/**
	 * 从包package中获取所有的Class
	 *
	 * @param pack
	 * @return
	 */
	public List<Class<?>> getClasses(Class clazz) {
		List<Class<?>> list = new ArrayList<Class<?>>();
		// 是否循环迭代
		boolean recursive = true;
		// 获取包的名字
		String packageName = clazz.getPackage().getName();
		String packageDirName = packageName.replace('.', '/');
		Enumeration<URL> dirs;
		try {
			dirs = Thread.currentThread().getContextClassLoader().getResources(packageDirName);
			// 循环迭代下去
			while (dirs.hasMoreElements()) {
				// 获取下一个元素
				URL url = dirs.nextElement();
				// 得到协议的名称
				String protocol = url.getProtocol();
				if ("jar".equals(protocol)) {
					// 如果是jar包文件
					// 定义一个JarFile
					JarFile jar;
					try {
						JarURLConnection openConnection = (JarURLConnection) url.openConnection();
						// 获取jar
						jar = openConnection.getJarFile();
						// 从此jar包 得到一个枚举类
						Enumeration<JarEntry> entries = jar.entries();
						// 同样的进行循环迭代
						while (entries.hasMoreElements()) {
							// 获取jar里的一个实体 可以是目录 和一些jar包里的其他文件 如META-INF等文件
							JarEntry entry = entries.nextElement();
							String name = entry.getName();
							// 如果是以/开头的
							if (name.charAt(0) == '/') {
								// 获取后面的字符串
								name = name.substring(1);
							}
							// 如果前半部分和定义的包名相同
							if (name.startsWith(packageDirName)) {
								int idx = name.lastIndexOf('/');
								// 如果以"/"结尾 是一个包
								if (idx != -1) {
									// 获取包名 把"/"替换成"."
									packageName = name.substring(0, idx).replace('/', '.');
								}
								// 如果可以迭代下去 并且是一个包
								if ((idx != -1) || recursive) {
									// 如果是一个.class文件 而且不是目录
									if (name.endsWith(".class") && !entry.isDirectory()) {
										// 去掉后面的".class" 获取真正的类名
										String className = name.substring(packageName.length() + 1, name.length() - 6);
										try {
											// 添加到classes
											list.add(Class.forName(packageName + '.' + className));
										} catch (ClassNotFoundException e) {
											// log.error("添加用户自定义视图类错误
											// 找不到此类的.class文件");
											e.printStackTrace();
										}
									}
								}
							}
						}
					} catch (IOException e) {
						// log.error("在扫描用户定义视图时从jar包获取文件出错");
						e.printStackTrace();
					}
				}
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
		return list;
	}

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值