• 【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 }

    结果如下

  • 相关阅读:
    C# 16 进制字符串转 int
    C# 16 进制字符串转 int
    dotnet 设计规范 · 抽象定义
    dotnet 设计规范 · 抽象定义
    C# 从零开始写 SharpDx 应用 控制台创建 Sharpdx 窗口
    C# 从零开始写 SharpDx 应用 控制台创建 Sharpdx 窗口
    C# 判断两条直线距离
    C# 判断两条直线距离
    PHP file() 函数
    PHP fgetss() 函数
  • 原文地址:https://www.cnblogs.com/a526583280/p/9745503.html
Copyright © 2020-2023  润新知