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

 package com.test.package_scanner.core;

 import java.io.File;
import java.io.FileFilter;
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; public abstract class PackageScanner { public PackageScanner() {
} // scanPackage方法的重载
public void scanPackage(Class<?> klass) {
scanPackage(klass.getPackage().getName());
} public void scanPackage(String packageName) {
// 将包名称转换为路径名称的形式
String packagePath = packageName.replace(".", "/"); try {
// 由类加载器得到URL的枚举
Enumeration<URL> resources = Thread.currentThread()
.getContextClassLoader()
.getResources(packagePath); while (resources.hasMoreElements()) {
URL url = resources.nextElement(); // 处理jar包
if (url.getProtocol().equals("jar")) {
parse(url);
} else {
File file = new File(url.toURI()); if (file.exists()) {
// 处理普通包
parse(file, packageName);
}
}
}
} catch (IOException e) {
e.printStackTrace();
} catch (URISyntaxException e) {
e.printStackTrace();
}
}
// 抽象方法,由用户自行处理扫描到的类
public abstract void dealClass(Class<?> klass); // jar包的扫描
private void parse(URL url) throws IOException {
Enumeration<JarEntry> jarEntries = ((JarURLConnection) url.openConnection())
.getJarFile().entries(); while (jarEntries.hasMoreElements()) {
JarEntry jarEntry = jarEntries.nextElement();
String jarName = jarEntry.getName(); if (!jarEntry.isDirectory() && jarName.endsWith(".class")) {
// 将文件路径名转换为包名称的形式
dealClassName(jarName.replace("/", ".").replace(".class", ""));
}
}
} // 普通包的扫描
private void parse(File curFile, String packageName) {
File[] fileList = curFile.listFiles(new FileFilter() {
// 筛选文件夹和class文件,其余文件不处理
@Override
public boolean accept(File pathname) {
return pathname.isDirectory() || pathname.getName().endsWith(".class");
}
}); // 目录就是一颗树,对树进行递归,找到class文件
for (File file : fileList) {
String fileName = file.getName();
if (file.isDirectory()) {
parse(file, packageName + "." + fileName);
} else {
String className = packageName + "." + fileName.replace(".class", "");
dealClassName(className);
}
}
} // 将找到的class文件生成类对象
private void dealClassName(String className) {
try {
Class<?> klass = Class.forName(className); // 注解、接口、枚举、原始类型不做处理
if (!klass.isAnnotation()
&& !klass.isInterface()
&& !klass.isEnum()
&& !klass.isPrimitive()) {
dealClass(klass);
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
} }

对如下目录扫描

 package com.test.package_scanner.demo;

 import com.test.package_scanner.core.PackageScanner;

 public class Demo {

     public static void main(String[] args) {
new PackageScanner() { @Override
public void dealClass(Class<?> klass) {
System.out.println(klass);
}
}.scanPackage("com");
} }

结果如下

【Java】包,jar包的扫描的更多相关文章

  1. java 执行 jar 包中的 main 方法

    java 执行 jar 包中的 main 方法 通过 OneJar 或 Maven 打包后 jar 文件,用命令: java -jar ****.jar执行后总是运行指定的主方法,如果 jar 中有多 ...

  2. Java常用jar包用途

    Java常用jar包用途: USAGE INDEX JAR NAME USAGE 1 ASM asm-2.2.3.jar ASM字节码库 2 ASM asm-commons-2.2.3.jar ASM ...

  3. (转)java 从jar包中读取资源文件

    (转)java 从jar包中读取资源文件 博客分类: java   源自:http://blog.csdn.net/b_h_l/article/details/7767829 在代码中读取一些资源文件 ...

  4. Python3.5调用Java的jar包

    声明:这个是在一个博客上看到的,过了俩星期了突然找不到原博客了,如果原来的博主看到,请联系我删除~ 主要是怕自己忘记,所以在此记录: 环境 Python3.5+JDK1.8 安装命令:python3 ...

  5. Java axis2.jar包详解及缺少jar包错误分析

    Java  axis2.jar包详解及缺少jar包错误分析 一.最小开发jar集 axis2 开发最小jar包集: activation-1.1.jar axiom-api-1.2.13.jar ax ...

  6. java执行jar包出错:Unable to access jarfile

    java执行jar包出错:Unable to access jarfile 错误的原因有多种: 1.一般都是路径不正确.在Windows中,正确的路径类似于: java -jar "D:\W ...

  7. java 生成jar包并保留注释

      java 生成jar包并保留注释 CreationTime--2018年7月17日08点32分 Author:Marydon 1.选中java项目-->右键-->Export: 2.去 ...

  8. 杂项-Java:jar 包与 war 包介绍与区别

    ylbtech-杂项-Java:jar 包与 war 包介绍与区别 1.返回顶部 1. 做Java开发,jar包和war包接触的挺多的,有必要对它们做一个深入的了解,特总结整理如下: 1.jar包的介 ...

  9. Java 的JAR包、EAR包、WAR包区别

    一.WAR包 WAR(Web Archive file) 网络应用程序文件,是与平台无关的文件格式,它允许将许多文件组合成一个压缩文件.WAR专用于Web方面.大部分的JAVA WEB工程,都是打成W ...

  10. 将java打jar包成linux后台服务service

    将java打jar包成linux后台服务service 第一步:将java程序打成jar包 build.gradle配置文件中加spring-boot-gradle-plugin插件,具体配置如下(配 ...

随机推荐

  1. sql server常用字符串函数

    --返回字符表达式中最左侧字符的ASCII代码值 --将整数ASCII代码转换为字符 )--a )--A ')--A SELECT CHAR('A')--在将 varchar 值 'A' 转换成数据类 ...

  2. R语言csv与txt文本读入区分(sep参数)

    R语言csv与txt文本读入区分 R语言用来处理数据很方便,而处理数据的第一步是把数据读入内存空间,平时最常用的文本数据储存格式有两种: 一种是CSV(逗号分隔符文本)另一种是TXT(Tab分隔符或空 ...

  3. JavaScript基础视频教程总结(021-030章)

    <!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title&g ...

  4. php中 curl, fsockopen ,file_get_contents 三个函数

    赵永斌:有些时候用file_get_contents()调用外部文件,容易超时报错.换成curl后就可以.具体原因不清楚curl 效率比file_get_contents()和fsockopen()高 ...

  5. 定时任务 Wpf.Quartz.Demo.5 (升级版)

    老规矩:先把全部源码上传,见本文底部. 相对于Demo3的区别,就是能自动加载继承了IJob的任务,任务主体程序分离. 在exe执行文件的同级下建一个MyJobs的文件夹,每次会自动扫描该文件夹下的J ...

  6. 「PKUWC2018」随机游走(min-max容斥+FWT)

    「PKUWC2018」随机游走(min-max容斥+FWT) 以后题目都换成这种「」形式啦,我觉得好看. 做过重返现世的应该看到就想到 \(min-max\) 容斥了吧. 没错,我是先学扩展形式再学特 ...

  7. redis key的过期时间

    设置redis key的生存过期时间 Redis 有四个不同的命令可以用于设置键的生存时间(键可以存在多久)或过期时间(键什么时候会被删除) : EXPlRE 命令用于将键key 的生存时间设置为tt ...

  8. 《你不知道的javascript》读书笔记2

    概述 放假读完了<你不知道的javascript>上篇,学到了很多东西,记录下来,供以后开发时参考,相信对其他人也有用. 这篇笔记是这本书的下半部分,上半部分请见<你不知道的java ...

  9. css插入背景图片底部有白边的解决方法

    相信很多小伙伴遇到过用CSS插入背景图时,底部出现白边的情况,如下图:   个人总结了2个方法如下: 解决方法1:给图片都加上 vertical-align: middle属性.有时,移动端也会有类似 ...

  10. Nginx---(main block)

    正常运行必备配置 1,user USERNAME [GROUPAME] ; 指定用于运行worker进程的用户和组:   user nginx nginx; 2, pid /PATH/TO/PID_F ...