【Java】包,jar包的扫描

包扫描在框架中应用很广泛,在spring中,通过给自己的类加注解的方式,利用spring的包扫描,完成依赖注入。

  1 package com.test.package_scanner.core;
  2 
  3 import java.io.File;
  4 import java.io.FileFilter;
  5 import java.io.IOException;
  6 import java.net.JarURLConnection;
  7 import java.net.URISyntaxException;
  8 import java.net.URL;
  9 import java.util.Enumeration;
 10 import java.util.jar.JarEntry;
 11 
 12 public abstract class PackageScanner {
 13 
 14     public PackageScanner() {
 15     }
 16     
 17     // scanPackage方法的重载
 18     public void scanPackage(Class<?> klass) {
 19         scanPackage(klass.getPackage().getName());
 20     }
 21     
 22     public void scanPackage(String packageName) {
 23         // 将包名称转换为路径名称的形式
 24         String packagePath = packageName.replace(".", "/");
 25         
 26         try {
 27             // 由类加载器得到URL的枚举
 28             Enumeration<URL> resources = Thread.currentThread()
 29                 .getContextClassLoader()
 30                 .getResources(packagePath);
 31             
 32             while (resources.hasMoreElements()) {
 33                 URL url = resources.nextElement();
 34                 
 35                 // 处理jar包
 36                 if (url.getProtocol().equals("jar")) {
 37                     parse(url);
 38                 } else {
 39                     File file = new File(url.toURI());
 40                     
 41                     if (file.exists()) {
 42                         // 处理普通包
 43                         parse(file, packageName);
 44                     }
 45                 }
 46             }
 47         } catch (IOException e) {
 48             e.printStackTrace();
 49         } catch (URISyntaxException e) {
 50             e.printStackTrace();
 51         }
 52     }
 53     // 抽象方法,由用户自行处理扫描到的类 
 54     public abstract void dealClass(Class<?> klass);
 55     
 56     // jar包的扫描
 57     private void parse(URL url) throws IOException {
 58         Enumeration<JarEntry> jarEntries = ((JarURLConnection) url.openConnection())
 59             .getJarFile().entries();
 60         
 61         while (jarEntries.hasMoreElements()) {
 62             JarEntry jarEntry = jarEntries.nextElement();
 63             String jarName = jarEntry.getName();
 64             
 65             if (!jarEntry.isDirectory() && jarName.endsWith(".class")) {
 66                 // 将文件路径名转换为包名称的形式
 67                 dealClassName(jarName.replace("/", ".").replace(".class", ""));
 68             }
 69         }
 70     }
 71     
 72     // 普通包的扫描
 73     private void parse(File curFile, String packageName) {
 74         File[] fileList = curFile.listFiles(new FileFilter() {
 75             // 筛选文件夹和class文件,其余文件不处理
 76             @Override
 77             public boolean accept(File pathname) {
 78                 return pathname.isDirectory() || pathname.getName().endsWith(".class");
 79             }
 80         });
 81         
 82         // 目录就是一颗树,对树进行递归,找到class文件
 83         for (File file : fileList) {
 84             String fileName = file.getName();
 85             if (file.isDirectory()) {
 86                 parse(file, packageName + "." + fileName);
 87             } else {
 88                 String className = packageName + "." + fileName.replace(".class", "");
 89                 dealClassName(className);
 90             }
 91         }
 92     }
 93     
 94     // 将找到的class文件生成类对象
 95     private void dealClassName(String className) {
 96         try {
 97             Class<?> klass = Class.forName(className);
 98             
 99             // 注解、接口、枚举、原始类型不做处理
100             if (!klass.isAnnotation()
101                     && !klass.isInterface()
102                     && !klass.isEnum()
103                     && !klass.isPrimitive()) {
104                 dealClass(klass);
105             }
106         } catch (ClassNotFoundException e) {
107             e.printStackTrace();
108         }
109     }
110     
111 }

对如下目录扫描

 1 package com.test.package_scanner.demo;
 2 
 3 import com.test.package_scanner.core.PackageScanner;
 4 
 5 public class Demo {
 6 
 7     public static void main(String[] args) {
 8         new PackageScanner() {
 9             
10             @Override
11             public void dealClass(Class<?> klass) {
12                 System.out.println(klass);
13             }
14         }.scanPackage("com");
15     }
16 
17 }

结果如下

posted @ 2018-10-05 18:46  松饼人  阅读(1058)  评论(0编辑  收藏  举报