ackage io.renren.common;

 import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils; import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
import java.net.JarURLConnection;
import java.net.URL;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Set;
import java.util.jar.JarEntry;
import java.util.jar.JarFile; @Slf4j
public class ClassUtil { /**
* 获取类加载器
* 获取加载器类的实现比较简单,只需获取当前线程的ClassLoader
*/
public static ClassLoader getClassLoader() {
return Thread.currentThread().getContextClassLoader();
} /**
* **
* 加载类
* 加载类需要提供类名与是否初始化的标志,这里提到的初始化指是否执行类的静态代码块;
* 为了提高加载类的性能,可以将loadClass方法的isInitialized参数设置false
*/
public static Class<?> loadClass(String className, boolean isInitialized) {
Class<?> cls = null;
try {
cls= Class.forName(className, isInitialized, getClassLoader());
} catch (ClassNotFoundException e) {
log.error("load class failure.", e);
throw new RuntimeException(e);
}
return cls;
} /**
* 获取指定包名下的所有类
*/
public static Set<Class<?>> getClassSet(String packageName) {
Set<Class<?>> classSet = new HashSet<Class<?>>();
try {
Enumeration<URL> urls = getClassLoader().getResources(packageName.replace(".", "/"));
while (urls.hasMoreElements()) {
URL url = urls.nextElement();
if (url != null) {
String protocol = url.getProtocol();
if ("file".equals(protocol)) {
String packagePath = url.getPath().replace("%20", "");
addClass(classSet, packagePath, packageName);
} else if ("jar".equals(protocol)) {
JarURLConnection jarURLConnection = (JarURLConnection) url.openConnection();
if (jarURLConnection != null) {
JarFile jarFile = jarURLConnection.getJarFile();
if (jarFile != null) {
Enumeration<JarEntry> jarEntries = jarFile.entries();
while (jarEntries.hasMoreElements()) {
JarEntry jarEntry = jarEntries.nextElement();
String jarEntryName = jarEntry.getName();
if (jarEntryName.endsWith(".class")) {
String className = jarEntryName.substring(0, jarEntryName.lastIndexOf("."))
.replaceAll("/", ".");
doAddClass(classSet, className);
}
}
}
}
}
}
}
} catch (IOException e) {
log.error("get class set failure.", e);
throw new RuntimeException(e);
}
return classSet;
} private static void addClass(Set<Class<?>> classSet, String packagePath, String packageName) {
File[] files = new File(packagePath).listFiles(new FileFilter() {
public boolean accept(File file) {
return (file.isFile() && file.getName().endsWith(".class")) || file.isDirectory();
}
});
for (File file : files) {
String fileName = file.getName();
if (file.isFile()) {
String className = fileName.substring(0, fileName.lastIndexOf("."));
if (StringUtils.isNotEmpty(packageName)) {
className = packageName + "." + className;
}
doAddClass(classSet, className);
} else {
String subPackagePath = fileName;
if (StringUtils.isNotEmpty(packageName)) {
subPackagePath = packagePath + "/" + subPackagePath;
}
String subPackageName = fileName;
if (StringUtils.isNotEmpty(packageName)) {
subPackageName = packageName + "." + subPackageName;
}
addClass(classSet, subPackagePath, subPackageName);
}
}
} private static void doAddClass(Set<Class<?>> classSet, String className) {
Class<?> cls = loadClass(className, true);
classSet.add(cls);
}

实现扫描包路径下类的功能

手写web框架之开发一个类加载器的更多相关文章

  1. 手写web框架之加载Controller,初始化框架

    1,加载Controller     我们需要创建 一个ControllerHelper类,让它来处理下面的逻辑:      通过ClassHelper我们可以获取所有定义了Controller注解的 ...

  2. 手写web框架之实现依赖注入功能

    我们在Controller中定义了Service成员变量,然后在Controller的Action方法中调用Service成员变量的方法,那么如果实现Service的成员变量? 之前定义了@Injec ...

  3. 手写web框架之实现Bean容器

    实现Bean容器    使用ClassHelper可以获取所加载的类,但无法通过类来实例化对象,因此我们需要提供一个反射工具类,让它封装java反射相关的API,对外提供更好用的工具方法.将该类命名为 ...

  4. 手写web框架之加载配置项目

    一  定义框架配置项 在项目的src/main/resources目录下创建一个名为smart.propertiesd的文件,文件的内容如下: smart.framework.jdbc.driver= ...

  5. 手写SpringMVC框架(二)-------结构开发设计

    续接前文, 手写SpringMVC框架(一)项目搭建 本节我们来开始手写SpringMVC框架的第二阶段:结构开发设计. 新建一个空的springmvc.properties, 里面写我们要扫描的包名 ...

  6. 手写DAO框架(二)-开发前的最后准备

    -------前篇:手写DAO框架(一)-从“1”开始 --------- 前言:前篇主要介绍了写此框架的动机,把主要功能点大致介绍了一下.此篇文章主要介绍开发前最后的一些准备.主要包括一些基础知识点 ...

  7. Web框架本质及第一个Django实例 Web框架

    Web框架本质及第一个Django实例   Web框架本质 我们可以这样理解:所有的Web应用本质上就是一个socket服务端,而用户的浏览器就是一个socket客户端. 这样我们就可以自己实现Web ...

  8. (二)springMvc原理和手写springMvc框架

    我们从两个方面了解springmvc执行原理,首先我们去熟悉springmvc执行的过程,然后知道原理后通过手写springmvc去深入了解代码中执行过程. (一)SpringMVC流程图 (二)Sp ...

  9. 手写SpringMVC 框架

    手写SpringMVC框架 细嗅蔷薇 心有猛虎 背景:Spring 想必大家都听说过,可能现在更多流行的是Spring Boot 和Spring Cloud 框架:但是SpringMVC 作为一款实现 ...

随机推荐

  1. PAT Basic 1052 卖个萌 (20 分)

    萌萌哒表情符号通常由“手”.“眼”.“口”三个主要部分组成.简单起见,我们假设一个表情符号是按下列格式输出的: [左手]([左眼][口][右眼])[右手] 现给出可选用的符号集合,请你按用户的要求输出 ...

  2. P5025 [SNOI2017]炸弹 题解

    蒟蒻的第一篇黑题题解(学了这么长时间了才第一道也是没谁了.) 题目链接: Solution: 朴素: 根据题目描述,我们可以处理每一个x节点左右爆炸半径范围内的点,然后模拟一次爆炸 (for),遍历每 ...

  3. 前端知识体系:JavaScript基础-变量和类型

    前端工程师自检清单 1. JavaScript规定了几种语言类型 2. JavaScript对象的底层数据结构是什么 3. Symbol类型在实际开发中的应用.可手动实现一个简单的 Symbo 4. ...

  4. Python JSONⅢ

    JSON 函数 encode Python encode() 函数用于将 Python 对象编码成 JSON 字符串. 语法 实例 以下实例将数组编码为 JSON 格式数据: 以上代码执行结果为: d ...

  5. 对JavaScript 模块化的深入-----------------引用

     什么是模块化 好的代码模块分割的内容一定是很合理的,便于你增加减少或者修改功能,同时又不会影响整个系统.  为什么要使用模块 1.可维护性:根据定义,每个模块都是独立的.良好设计的模块会尽量与外部的 ...

  6. goproxy

    go env -w GOPROXY=https://goproxy.cn,directgo env -w GO111MODULE=ongo env -w GOBIN=$HOME/bin (可选)go ...

  7. nginx配置项

    try_files location / { try_files $uri $uri/ /index.php?$query_string; } 当用户请求 http://host/instance时, ...

  8. apply, bind, call--绑定this的方法

    Function.prototype.call(),Function.prototype.apply(),Function.prototype.bind() 是三种改变函数内部this指向(即函数执行 ...

  9. jQuery系列(十三):实现轮播

    1.轮播一: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UT ...

  10. Mac Appium环境搭建

    安装brew ruby -e "$(curl -fsSL https://raw.github.com/mxcl/homebrew/go)" 安装java brew install ...