【JAVA】包扫描及jar包扫描工具的设计

包扫描的作用:

按指定包路径和要求扫描出符合条件的类,并反射出它们的类类型,在此基础上进行各种操作。

如:扫描包内含有注解的类并进行处理等。

我们的需求是对普通类进行处理的,所以在扫描时应当排除接口、枚举、注解、以及八大基本类型。

此外,在实际应用时,针对在扫描出类后所要进行的,不能在编写工具时期所能确定的操作,我们给出一个抽象方法,在扫描出每个符合条件的类后调用这个抽象方法。要求用户在实际应用时实现此方法。

	public abstract void dealClass(Class<?> klass);

普通包扫描:

private void packageScan(String pathname, File currentFile) {
    //File类的对象表示一个文件或文件夹
    //FileFilter起到一个文件过滤器的作用,其中的accept()方法体现出了筛选过程
	File[] fileList = currentFile.listFiles(new FileFilter() {
        //只筛选出“.class”和文件夹的File对象
		@Override
    		public boolean accept(File pathname) {
			if(pathname.isDirectory()) {
				return true;
			}
			return pathname.getName().endsWith(".class");
		}
	});
		
	for(File file : fileList) {
		String fileName = file.getName();
		if(file.isDirectory()) {
            //构建出当前文件夹所表示的包路径,递归扫描
		    packageScan(pathname + "." + file.getName(), file);
		} else {
            //构建出类名称并进行反射,进一步筛选
			String className = pathname + "." + fileName.replace(".class", "");
			try {
				Class<?> klass = Class.forName(className);
				if(klass.isAnnotation() 
						|| klass.isInterface()
						|| klass.isEnum() 
						|| klass.isPrimitive()) {
					continue;
				}
				
				dealClass(klass);//未来的处理
			} catch (ClassNotFoundException e) {
				e.printStackTrace();
			}
		}
	}
}
	

Jar包扫描:

至于jar包扫描,需要用到一些前人所提供的工具,初学者看到也不必惊慌,拿来用就是了。

private void scanPackage(URL url) throws IOException {
	JarURLConnection urlConnection = (JarURLConnection) url.openConnection();
	JarFile jarFile = urlConnection.getJarFile();
	Enumeration<JarEntry> jarEntries = jarFile.entries();
	while (jarEntries.hasMoreElements()) {
		JarEntry jarEntry = jarEntries.nextElement();
		String jarName = jarEntry.getName();
		if (jarEntry.isDirectory() || !jarName.endsWith(".class")) {
			continue;
		}
		String className = jarName.replace(".class", "").replaceAll("/", ".");
		try {
			Class<?> klass = Class.forName(className);
			if (klass.isAnnotation() 
					|| klass.isInterface()
					|| klass.isEnum()
					|| klass.isPrimitive()) {
				continue;
			}
			dealClass(klass);
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
	}
}

综合:


public void packageScan(String pathname) {
	String opperPathname = pathname.replace('.', '/');
	//得到当前上下文的类加载器(动态加载类到JVM中)
	ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
	
	 try {
		Enumeration<URL> resources = classLoader.getResources(opperPathname);
		while(resources.hasMoreElements()) {
			URL url = resources.nextElement();
			if(url.getProtocol().equals("jar")) {
				//扫描jar包
				scanPackage(url);
			} else {
                    //普通包扫描
				File file = new File(url.toURI());
				if (!file.exists()) {
					continue;
				}
				packageScan(pathname, file);
			}
		}
	} catch (IOException e) {
		e.printStackTrace();
	} catch (URISyntaxException e) {
		e.printStackTrace();
	}
}

这样包扫描的基本功能就完成了。在此基础上我们在给上几种方法的重载,让我们的工具能适应的情况多一些。

public void packageScan(Class<?> klass) {
	packageScan(klass.getPackage().getName());
}

public void packageScan(Class<?>[] classes) {
	for(Class<?> klass : classes) {
		packageScan(klass);
	}
}

public void packageScan(String[] packages) {
	for(String packageName : packages) {
		packageScan(packageName);
	}
}

感谢西安微易码科技公司金牌讲师朱洪老师的悉心指导。

转载请注明出处。

猜你喜欢

转载自blog.csdn.net/coinph/article/details/83385200
今日推荐