手写web框架之开发一个类加载器
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框架之开发一个类加载器的更多相关文章
- 手写web框架之加载Controller,初始化框架
1,加载Controller 我们需要创建 一个ControllerHelper类,让它来处理下面的逻辑: 通过ClassHelper我们可以获取所有定义了Controller注解的 ...
- 手写web框架之实现依赖注入功能
我们在Controller中定义了Service成员变量,然后在Controller的Action方法中调用Service成员变量的方法,那么如果实现Service的成员变量? 之前定义了@Injec ...
- 手写web框架之实现Bean容器
实现Bean容器 使用ClassHelper可以获取所加载的类,但无法通过类来实例化对象,因此我们需要提供一个反射工具类,让它封装java反射相关的API,对外提供更好用的工具方法.将该类命名为 ...
- 手写web框架之加载配置项目
一 定义框架配置项 在项目的src/main/resources目录下创建一个名为smart.propertiesd的文件,文件的内容如下: smart.framework.jdbc.driver= ...
- 手写SpringMVC框架(二)-------结构开发设计
续接前文, 手写SpringMVC框架(一)项目搭建 本节我们来开始手写SpringMVC框架的第二阶段:结构开发设计. 新建一个空的springmvc.properties, 里面写我们要扫描的包名 ...
- 手写DAO框架(二)-开发前的最后准备
-------前篇:手写DAO框架(一)-从“1”开始 --------- 前言:前篇主要介绍了写此框架的动机,把主要功能点大致介绍了一下.此篇文章主要介绍开发前最后的一些准备.主要包括一些基础知识点 ...
- Web框架本质及第一个Django实例 Web框架
Web框架本质及第一个Django实例 Web框架本质 我们可以这样理解:所有的Web应用本质上就是一个socket服务端,而用户的浏览器就是一个socket客户端. 这样我们就可以自己实现Web ...
- (二)springMvc原理和手写springMvc框架
我们从两个方面了解springmvc执行原理,首先我们去熟悉springmvc执行的过程,然后知道原理后通过手写springmvc去深入了解代码中执行过程. (一)SpringMVC流程图 (二)Sp ...
- 手写SpringMVC 框架
手写SpringMVC框架 细嗅蔷薇 心有猛虎 背景:Spring 想必大家都听说过,可能现在更多流行的是Spring Boot 和Spring Cloud 框架:但是SpringMVC 作为一款实现 ...
随机推荐
- Map的使用及遍历方式
Java中Map遍历的四种方式 如果同时需要key和value推荐使用entrySet(第一种): 如果只是获取key,或者value,推荐使用keySet或者values方式(第二种): 如果需要在 ...
- TCP协议之网络延时
影响TCP 网络时延的因素硬件速度网络和服务器的负载请求和响应报文的尺寸客户端和服务器之间的距离TCP 协议的技术复杂性TCP协议产生的时延TCP 连接建立握手:TCP 慢启动拥塞控制:数据聚集的 N ...
- rac 数组之遍历
rac的数组遍历其实很简单.但是有个点需要注意. 以下先举个例子说明遍历的用法 NSArray *temArr = @["]; [temArr.rac_sequence.signal sub ...
- .configurable:可配执行 .enumerble:枚举性 .writable:可读写性 .value:数据值
configurable:控制属性能否被删除,只有当属性的configurable特性的值为true时,该属性才能够被删除. 默认值为false,即不可删除) var person = {}; Obj ...
- 浅谈script中的defer与async
一直没有在script上使用过别的属性,今天看基础代码才发现这个,搜索.记录下,以便记忆. 大家都知道,js加载会造成阻塞,阻碍页面的继续渲染. defer: js与页面同步加载,不阻碍页面渲染,会在 ...
- springboot整合easyexcel实现Excel导入导出
easyexcel:快速.简单避免OOM的java处理Excel工具 Java解析.生成Excel比较有名的框架有Apache poi.jxl.但他们都存在一个严重的问题就是非常的耗内存,poi有一套 ...
- 4、docker镜像:花卷结构、commit镜像
1.是什么 docker images 镜像是一种轻量级.可执行的独立软件包,用来打包软件运行环境和基于运行环境开发的软件,它包含运行某个软件所需的所有内容,包括代码.运行时.库.环境变量和配置文件. ...
- Nginx的TCP/UDP调度器
安装nginx [root@proxy ~]# yum –y install gcc pcre-devel openssl-devel //安装依赖包 [root@proxy ~]# .tar.gz ...
- BOOTING ELOQUENT MODEL TRAITS
BOOTING ELOQUENT MODEL TRAITS So I've learnt a little Laravel/Eloquent trick today that is very much ...
- 求后序遍历x
题目描述 Description 输入一棵二叉树的先序和中序遍历序列,输出其后序遍历序列. 输入描述 Input Description 共两行,第一行一个字符串,表示树的先序遍历,第二行一个字符串, ...