手写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 作为一款实现 ...
随机推荐
- PAT Advanced 1020 Tree Traversals (25 分)
1020 Tree Traversals (25 分) Suppose that all the keys in a binary tree are distinct positive integ ...
- Vasya and Beautiful Arrays CodeForces - 354C (数论,枚举)
Vasya and Beautiful Arrays CodeForces - 354C Vasya's got a birthday coming up and his mom decided to ...
- R的数据结构--向量
向量:用于存储数值型.字符型或逻辑型数据的一维数组,只可以包含一种数据 向量的创建与运算 创建向量 # 创建简单向量 l <- c(2, 2, 1, 3, 8) # [1] 2 2 1 3 8 ...
- 《黑白团团》第九次团队作业:Beta冲刺与验收准备
项目 内容 作业课程地址 任课教师首页链接 作业要求 团队项目 填写团队名称 黑白团团队 填写具体目标 认真负责,完成项目 GitHub链接 Scrum meeting导航 [Beta]Scrum m ...
- 回顾了下shell 编程的一些细节
回顾了一些细节 shell 的通配符扩展 * ? [] [^xxxx] {aaa,bbb} 子进程 more `grep -l POSIX *` more $(grep -l ...
- 转:SpringBoot 自定义异常@ContollerAdvice ExceptionHandler不起作用
原文链接:https://blog.csdn.net/evanxuhe/article/details/78650979 为了统一异常,我们通常定义一个统一管理所有Exception,包括自定义Exc ...
- python常用函数拾零
Python常用内置函数总结: 整理过程中参考了runoob网站中python内置函数的相关知识点,特此鸣谢!! 原文地址:http://www.runoob.com/python/python-bu ...
- App自动化-python-Unittest框架
TestCase: 一段Testcase代码示例: # -*- coding: utf-8 -*- ''' Created on 2019-6-27 @author: adminstrator ''' ...
- JVM(十一),垃圾回收之老年代垃圾收集器
十一.垃圾回收之老年代垃圾收集器 1.Serial Old收集器(标记整理算法-单线程-Client模式下) 2.Paraller Old收集器(标记整理算法-多线程-) 3.CMS收集器(标记清除算 ...
- 百度ueditor实现word图片自动转存
官网地址http://ueditor.baidu.com Git 地址 https://github.com/fex-team/ueditor 参考博客地址 http://blog.ncmem.com ...