利用URLClassLoader读取Jar包并反射类(利用Tomcat源码)
来源:互联网 发布:java正则表达式$ 编辑:程序博客网 时间:2024/05/20 09:10
第一次写博客,写的不好请见谅。
背景:在公司内部项目中碰到了一个需求,我需要读取本地jar包然后反射其中的实体类来获取其类名、属性等字段并保存。
分析:显然,我们首先需要用到反射,但是反射需要有类加载器来加载类。比如classLoader.load("com.test.Test");对加载器不了解的朋友可以自行百度。因为是读的本地的jar包,我们当前web用的appClassLoader显然不够用,也无法load本地的类,因此我们可以自己使用URLClassLoader创建一个加载器。(在这里我是用了tomcat生成自定义classloader的方法,很简单)。
方法:将jar存在项目根路径下,创建ClassLoader之前获取jar包的所有路径即可。
实施:
/** * 创建classloader(调用了tomcat的api) * @return * @throws Exception */private ClassLoader createClassLoader() throws Exception { //在这里拿到存在本地的jar包的路径 //模仿tomcat的处理方式 String value = JarProperties.getProperty("jar.path"); if (value == null) { return null; } //处理字符串路径 value = replace(value); List<ClassLoaderFactory.Repository> repositories = new ArrayList<>(); //分割成路径数组 String[] repositoryPaths = getPaths(value); for (String repository : repositoryPaths) { // Local repository if (repository.endsWith("*.jar")) { repository = repository.substring (0, repository.length() - "*.jar".length()); repositories.add( new ClassLoaderFactory.Repository(repository, ClassLoaderFactory.RepositoryType.GLOB)); } else if (repository.endsWith(".jar")) { repositories.add( new ClassLoaderFactory.Repository(repository, ClassLoaderFactory.RepositoryType.JAR)); } else { repositories.add( new ClassLoaderFactory.Repository(repository, ClassLoaderFactory.RepositoryType.DIR)); } } return ClassLoaderFactory.createClassLoader(repositories, null);}
其中JarProperties如下:
public class JarProperties { private static final Logger logger = LoggerFactory.getLogger(JarProperties.class); private static Properties properties = null; static { loadProperties(); } /** * @param name The property name * @return specified property value */ public static String getProperty(String name) { return properties.getProperty(name); } private static void loadProperties() { InputStream is = null; try { ClassLoader cl = JarProperties.class.getClassLoader(); URL url = cl.getResource("jar.properties"); if (url != null) { is = url.openStream(); } } catch (Exception e) { e.printStackTrace(); logger.error("url打开stream错误");// logger.error(e.getMessage() + "没有找到.properties文件"); } if (is != null) { try { properties = new Properties(); properties.load(is); } catch (Exception e) { e.printStackTrace(); logger.error("加载jar.properties文件出错"); } finally { try { is.close(); } catch (IOException e) { e.printStackTrace(); logger.error("无法关闭jar.properties" + e); } } } if (is == null) { // Do something logger.error("没有找到jar.properties文件"); // That's fine - we have reasonable defaults. properties = new Properties(); } }}jar.properties:jar.path = "${authority.home}/jar","${authority.home}/jar/*.jar"然后在ClassLoaderFactory.createClassLoader(repositories, null)中:
/** * Create and return a new class loader, based on the configuration * defaults and the specified directory paths: * * @param repositories List of class directories, jar files, jar directories * or URLS that should be added to the repositories of * the class loader. * @param parent Parent class loader for the new class loader, or * <code>null</code> for the system class loader. * @return the new class loader * * @exception Exception if an error occurs constructing the class loader */public static ClassLoader createClassLoader(List<Repository> repositories, final ClassLoader parent) throws Exception { if (log.isDebugEnabled()) log.debug("Creating new class loader"); // Construct the "class path" for this class loader Set<URL> set = new LinkedHashSet<>(); if (repositories != null) { for (Repository repository : repositories) { if (repository.getType() == RepositoryType.URL) { URL url = buildClassLoaderUrl(repository.getLocation()); if (log.isDebugEnabled()) log.debug(" Including URL " + url); set.add(url); } else if (repository.getType() == RepositoryType.DIR) { File directory = new File(repository.getLocation()); directory = directory.getCanonicalFile(); if (!validateFile(directory, RepositoryType.DIR)) { continue; } URL url = buildClassLoaderUrl(directory); if (log.isDebugEnabled()) log.debug(" Including directory " + url); set.add(url); } else if (repository.getType() == RepositoryType.JAR) { File file=new File(repository.getLocation()); file = file.getCanonicalFile(); if (!validateFile(file, RepositoryType.JAR)) { continue; } URL url = buildClassLoaderUrl(file); if (log.isDebugEnabled()) log.debug(" Including jar file " + url); set.add(url); } else if (repository.getType() == RepositoryType.GLOB) { File directory=new File(repository.getLocation()); directory = directory.getCanonicalFile(); if (!validateFile(directory, RepositoryType.GLOB)) { continue; } if (log.isDebugEnabled()) log.debug(" Including directory glob " + directory.getAbsolutePath()); String filenames[] = directory.list(); if (filenames == null) { continue; } for (int j = 0; j < filenames.length; j++) { String filename = filenames[j].toLowerCase(Locale.ENGLISH); if (!filename.endsWith(".jar")) continue; File file = new File(directory, filenames[j]); file = file.getCanonicalFile(); if (!validateFile(file, RepositoryType.JAR)) { continue; } if (log.isDebugEnabled()) log.debug(" Including glob jar file " + file.getAbsolutePath()); URL url = buildClassLoaderUrl(file); set.add(url); } } } } // Construct the class loader itself final URL[] array = set.toArray(new URL[set.size()]); if (log.isDebugEnabled()) for (int i = 0; i < array.length; i++) { log.debug(" location " + i + " is " + array[i]); } return AccessController.doPrivileged( new PrivilegedAction<URLClassLoader>() { @Override public URLClassLoader run() { if (parent == null) return new URLClassLoader(array); else return new URLClassLoader(array, parent); } });}具体注释我就不写了,就是把路径处理一下然后放在数组中然后new URLClassLoader(array)就可以。大部分代码都是tomcat源码中的,我是直接用的tomcat的类完成的这个接口。所以说,多看源码还是很有帮助滴。
人生第一篇博客结束!!!!!
阅读全文
1 0
- 利用URLClassLoader读取Jar包并反射类(利用Tomcat源码)
- 【动态页面】(三)之一:利用Java反射机制读取Jar包的类名和属性名
- Java 利用反射调用jar包中的类
- 利用反射动态获取当前工程下的文件路径_并打成jar包
- 利用bat反编译jar包生成源码jar包
- 利用bat反编译jar包生成源码jar包
- 利用bat反编译jar包生成源码jar包
- jsp利用jspsmartupload.jar包上传源码和jar包
- URLClassLoader加载jar包
- 利用反射打印出 Jar包中所有的类名和方法
- 利用反射机制,读取dll,并调用其中的方法
- 利用反射读取类的私有变量
- 利用反射读取类的私有变量
- 利用Eclipse+maven编译Jedis源码成jar包和源码jar包
- 利用Eclipse+maven编译Jedis源码成jar包和源码jar包
- 利用 javaService 发布服务(jar包)
- 利用RODBC包读取并展示xls文件内容
- 反射应用(读取war包、jar包里的类,获得annotation的值)
- SpringMVC RESTful风格CURD并集成Swagger2
- JavaWeb使用SpringMVC的简单案例
- 2017多校训练第二场 hdu6050 Funny Function(数学+快速幂+逆元)
- sql语句给数据库减肥,下面以网狐6603源码搭建为案例
- linux 调度总结
- 利用URLClassLoader读取Jar包并反射类(利用Tomcat源码)
- java分布式服务框架Dubbo的介绍与使用
- UVA 11817 Tunnelling the Earth
- Balala Power!
- Java_基础—标准输入输出流概述和输出语句
- fmpeg 时间戳问题汇总
- Csharp
- 自定义View-----语音识别+识别中状态
- localStorage(web存储)的用法