包扫描工具实现(详解)

news2024/12/22 19:01:19

文章目录

  • 前言
  • 包扫描
    • 实现思路(需求分析):
  • 具体实现
  • 完整代码

前言

注解在 Java 是一个非常重要的存在,而且它出现的非常频繁。

在一个工程下可能有许多的包或者Jar包,为了结合注解可以准确的定位到一个需要的类上,并且扫描到一个包下的所有类方便我们使用反射机制,所以产生了包扫描工具实现的想法,它可以帮我们找到带有注解的类,再通过反射执行。

包扫描

我们可以通过用户提供的包名,扫描该包下的所有类。

实现思路(需求分析):

通过博主思考,我们需要实现功能:

  • 一个工程下存在普通包或者Jar包,分开处理 Jar 包和普通包;

  • 得到该包下我们所要找的类(例如:带有注解的类或者接口或者枚举类型等)这里主要用于扫描带有注解的类。

因为通过包扫描找到该类,我们可以通过注解信息得到该类里面带有注解的成员或方法的信息,然后通过反射机制执行。

具体实现

  • 创建一个 IClassDealer接口:
public interface IClassDealer {
	void classDealer(Class<?> klass);
}
  • 包扫描类实现:

    • 这里根据包名,通过得到 url 协议名称,然后判断是 Jar 包还是普通包,如果是普通包就调用 fileScan(String packageName, File dir)这个方法,进行普通包扫描,如果是 Jar 包,就调用jarScan(String packageName, URL url),进行 Jar 扫描。

      	public void scanPackage(String packageName) throws URISyntaxException {
      		String packagePath = packageName.replace(".", "/");
      		URL url = Thread.currentThread().getContextClassLoader().getResource(packagePath);
      		if (url.getProtocol().equals("file")) {
      			File root = new File(url.toURI());
      			fileScan(packageName, root);
      		} else if (url.getProtocol().equals("jar")) {
      			try {
      				jarScan(packageName, url);
      			} catch (IOException e) {
      				e.printStackTrace();
      			}
      		}
      	}
      
    • 普通包扫描

      	private void fileScan(String packageName, File dir) {
      		File[] files = dir.listFiles();
      		for (File file : files) {
      			if (file.isDirectory()) {
      				fileScan(packageName + "." + file.getName(), file);
      			} else {
      				String fileName = file.getName();
      				if (!fileName.endsWith(".class") || fileName.contains("$")) {
      					continue;
      				}
      				fileName = fileName.replace(".class", "");
      				String className = packageName  + "." + fileName;
      				try {
      					Class<?> klass = Class.forName(className);
      					classDealer.classDealer(klass);
      				} catch (ClassNotFoundException e) {
      					e.printStackTrace();
      					continue;
      				}
      			}
      		}
      	}
      
    • Jar 扫描

      	private void jarScan(String packageName, URL url) throws IOException {
      		JarURLConnection connection = (JarURLConnection) url.openConnection();
      		JarFile jarFile = connection.getJarFile();
      		Enumeration<JarEntry> entries = jarFile.entries();
      		while (entries.hasMoreElements()) {
      			JarEntry entry = entries.nextElement();
      			String entryName = entry.getName();
      			String className = entryName.replace("/", ".");
      			
      			if (!className.startsWith(packageName) || className.contains("$") || !entryName.endsWith(".class")) {
      				continue;
      			}
      			className = className.replace(".class", "");
      			try {
      				Class<?> klass = Class.forName(className);
      				classDealer.classDealer(klass);
      			} catch (ClassNotFoundException e) {
      				e.printStackTrace();
      			}
      		}
      	}
      

完整代码

  • 创建一个 IClassDealer接口:
public interface IClassDealer {
	void classDealer(Class<?> klass);
}
  • 包扫描具体代码:
package com.hb.util;

import java.io.File;
import java.io.IOException;
import java.net.JarURLConnection;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.Enumeration;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;

public class PackageScanner {
    /**
    *因为扫描到的类的相关具体操作不是本工具需要完成的,
	*因此给一个接口,具体操作由工具使用者完成。
	*用这个方法可以去筛选使用者需要扫描的包下的类达到自己的目的。
    */
	private IClassDealer classDealer;
	
	public PackageScanner() {
		this.classDealer = new IClassDealer() {
			@Override
			public void classDealer(Class<?> klass) {
			}
		};
	}

	public PackageScanner addClassDealer(IClassDealer classDealer) {
		this.classDealer = classDealer;
		return this;
	}

	public void scanPackage(String packageName) throws URISyntaxException {
		String packagePath = packageName.replace(".", "/");
		URL url = Thread.currentThread().getContextClassLoader().getResource(packagePath);
		if (url.getProtocol().equals("file")) {
			File root = new File(url.toURI());
			fileScan(packageName, root);
		} else if (url.getProtocol().equals("jar")) {
			try {
				jarScan(packageName, url);
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
	
	private void jarScan(String packageName, URL url) throws IOException {
		JarURLConnection connection = (JarURLConnection) url.openConnection();
		JarFile jarFile = connection.getJarFile();
		Enumeration<JarEntry> entries = jarFile.entries();
		while (entries.hasMoreElements()) {
			JarEntry entry = entries.nextElement();
			String entryName = entry.getName();
			String className = entryName.replace("/", ".");
			
			if (!className.startsWith(packageName) || className.contains("$") || !entryName.endsWith(".class")) {
				continue;
			}
			className = className.replace(".class", "");
			try {
				Class<?> klass = Class.forName(className);
				classDealer.classDealer(klass);
			} catch (ClassNotFoundException e) {
				e.printStackTrace();
			}
		}
	}
	
	private void fileScan(String packageName, File dir) {
		File[] files = dir.listFiles();
		for (File file : files) {
			if (file.isDirectory()) {
				fileScan(packageName + "." + file.getName(), file);
			} else {
				String fileName = file.getName();
				if (!fileName.endsWith(".class") || fileName.contains("$")) {
					continue;
				}
				fileName = fileName.replace(".class", "");
				String className = packageName  + "." + fileName;
				try {
					Class<?> klass = Class.forName(className);
					classDealer.classDealer(klass);
				} catch (ClassNotFoundException e) {
					e.printStackTrace();
					continue;
				}
			}
		}
	}
}

测试运行结果:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/609946.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

代码随想录算法训练营第四十六天|139.单词拆分

LeetCode139.单词拆分 动态规划五部曲&#xff1a; 1&#xff0c;确定dp数组以及下标的含义&#xff1a; dp[i] : 字符串长度为i的话&#xff0c;dp[i]为true&#xff0c;表示可以拆分为一个或多个在字典中出现的单词。 2&#xff0c;确定递推公式&#xff1a; 如果确定dp[j…

javascript基础二十:说说你对DOM的理解,常见的操作有哪些?

一、DOM 文档对象模型 (DOM) 是 HTML 和 XML 文档的编程接口 它提供了对文档的结构化的表述&#xff0c;并定义了一种方式可以使从程序中对该结构进行访问&#xff0c;从而改变文档的结构&#xff0c;样式和内容 任何 HTML或XML文档都可以用 DOM表示为一个由节点构成的层级结构…

交通物流模型 | Python建模实现动态交通分配优化问题求解

文章目录 效果一览文章概述研究内容程序设计参考资料效果一览 文章概述 交通物流模型 | Pyomo建模框架实现动态交通分配优化问题求解,DTA 交通分配问题通常需要考虑许多因素,例如道路容量、交通需求、速度限制、车辆类型、交通信号灯等,在城市规划和交通管理领域中具有重要的…

分布式系统概念和设计——分布式事务

分布式系统概念和设计 分布式事务 访问多个服务器管理的对象的事务称为分布式事务。 当一个分布式事务结束时&#xff0c;事务的原子特性要求所有参与事务的服务器必须全部提交或全部放弃。 实现&#xff1a; 其中一个服务器承担了协调者的角色&#xff0c;保证在所有的服务器…

chatgpt赋能python:Python图片取模:提高网页加载速度与用户体验

Python图片取模&#xff1a;提高网页加载速度与用户体验 随着互联网的发展与全球化进程的加速&#xff0c;网站的速度与易用性成为用户选择网站的重要因素。在这种情况下&#xff0c;我们需要优化网站的加载速度与用户体验。其中一种优化方法就是使用图片取模。 本文将向您介…

chatgpt赋能python:Python图像处理技术:学习Python,掌握图像处理!

Python图像处理技术&#xff1a;学习Python&#xff0c;掌握图像处理&#xff01; 在当今时代&#xff0c;图像处理已成为现代生活中不可或缺的一部分&#xff0c;从照片、视频到尖端医疗设备中的医学图像&#xff0c;都需要使用图像处理技术。Python图像处理技术是当今广泛使…

2023年淘宝天猫京东618活动时间安排和活动攻略

2023年淘宝天猫京东618活动力度大吗&#xff1f;活动什么时候开始&#xff1f;有什么省钱技巧&#xff1f;让我们来一起看一下&#xff01; 2023年淘宝618活动一览 时间安排 第一波(开门红) 预售时间&#xff1a;5月26日 14:00-5月26日 20:00 定金时间&#xff1a;5月26日 …

快排+归并

&#x1f947;快排 &#x1f380;快排题目 &#x1f3ab;快排代码实现 #include<iostream> using namespace std; const int N100010;//定义一个只读变量 int a[N]{0};//开辟空间&#xff0c;定义全局变量&#xff0c;后来就不用传参了 void quicksort1(int l,int r) {…

(三)多文件云传输框架项目实现(详解)

文章目录 前言《多文件云传输》框架概述简介技术实现框架基本思想 《多文件云传输》框架思考需求分析 《多文件云传输》框架实现数据基础实现技术难点实现 前言 《多文件云传输》框架的实现是本人的一个编程训练项目&#xff0c;为了提升本人的编程能力、JAVA 编程思想&#x…

第二章 数据类型、运算符与表达式

如何打开项目 如何打开已经存在的解决方案&#xff1f; 找到要打开的解决方案目录&#xff0c;进去之后双击后缀为.sln的文件即可打开该解决方案。 或者从最近打开项目中打开&#xff1a; Online Judge使用 OJ简介 在线判题系统&#xff08;Online Judge&#xff0c;缩写OJ…

GIN框架(GOLANG)讲解如何疯速入门

1.初始化项目&#xff1a; 1.初始化项目&#xff1a;go mod init 2.下载gin框架&#xff1a;go get -u github.com/gin-gonic/gin 3.引入&#xff1a;import "github.com/gin-gonic/gin" 注意点&#xff1a; 报错&#xff1a;$GOPATH/go.mod exists but should …

Python可视化分析项目

今天给大家分享一个基于python的django框架结合爬虫以及数据可视化和数据库的项目&#xff0c;该项目总体来说还是挺不错的&#xff0c;下面针对这个项目做具体介绍。 1&#xff1a;项目涉及技术&#xff1a; 项目后端语言&#xff1a;python 项目页面布局展现&#xff1a;前…

代码随想录算法训练营第四十二天|416. 分割等和子集

LeetCode416. 分割等和子集 背包问题&#xff0c;有N件物品和一个最多能背重量为W 的背包。第i件物品的重量是weight[i]&#xff0c;得到的价值是value[i] 。每件物品只能用一次&#xff0c;求解将哪些物品装入背包里物品价值总和最大。背包问题有多种背包方式&#xff0c;常见…

地理探测器的应用方法

关于地理探测器的使用&#xff0c;网络上有大量的教学视频及资料&#xff0c;既可以用Excel计算&#xff0c;也可以利用R语言计算&#xff0c;本文主要分享利用Excel计算的方法&#xff0c;借鉴了大量的学习资料&#xff0c;记录一下供自己参考&#xff0c;也希望能帮到有需要的…

CLR via C#(一)CLR的执行模型

一、什么是CLR CLR全称Common Language Runtime&#xff0c;即公共语言运行时。它可以为所有面向CLR的语言提供运行时的内存管理、程序集加载、安全性、异常处理和线程同步等功能。 事实上&#xff0c;CLR并不关心开发者使用的到底是哪种语言&#xff0c;只要这门语言的编译器…

chatgpt赋能python:Python图像处理优化技巧:提高网站SEO效果的必修课程

Python图像处理优化技巧&#xff1a;提高网站SEO效果的必修课程 介绍 在当前数字化时代&#xff0c;网站的SEO优化已经成为了网站营销的重要一环。在优化网站SEO的同时&#xff0c;提升图像处理技巧也成为了重要的一环。Python作为当前最为火热的数据科学语言之一&#xff0c…

chatgpt赋能python:Python计算圆柱体积的方法

Python计算圆柱体积的方法 Python是一种广泛使用的编程语言&#xff0c;由于其易于学习和使用的特点&#xff0c;许多人在业余时间选择了学习Python。Python可以用来解决各种计算问题&#xff0c;其中包括计算圆柱体积。在本文中&#xff0c;我们将探讨如何使用Python计算圆柱…

chatgpt赋能python:Python在一个程序里调用另一段程序

Python在一个程序里调用另一段程序 随着Python程序的复杂度越来越高&#xff0c;有时候一个程序难以处理所有的任务。这时候我们可能需要将任务拆分成多个脚本来执行。但是&#xff0c;这会导致代码的复杂性增加&#xff0c;同时也会增加可读性和维护成本。这时候&#xff0c;…

LeetCode排序数组(常用排序一一实现)

912. 排序数组 - 力扣&#xff08;LeetCode&#xff09; 这道题他会设置一个数据量特别特别大的案例&#xff0c;对于一般的算法是一定过不去的 1.冒泡排序---这种的时间复杂度是O(n*n)&#xff0c;对于这道题是不可能过得去的 /*** Note: The returned array must be malloce…

EMQX将数据发送到后端

本文主要是记录了使用免费的EMQX的数据集成功能&#xff0c;将数据流转到后端平台。 在实现过程中&#xff0c;首先是在云服务器之中下载了EMQX&#xff0c;之后通过EMQX的数据集成功能&#xff0c;创建了数据桥接以及与之对应的规则&#xff0c;可以实现将EMQX接收到的数据转发…