All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.alibaba.toolkit.util.ContextClassLoader Maven / Gradle / Ivy

The newest version!
/*
 * Copyright (c) 2002-2012 Alibaba Group Holding Limited.
 * All rights reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.alibaba.toolkit.util;

import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Method;
import java.net.URL;
import java.util.Enumeration;
import java.util.Set;

import com.alibaba.toolkit.util.collection.ArrayHashSet;

/**
 * 

* 查找并装入类和资源的辅助类. *

*

* ClassFinder查找类和资源的效果, 相当于ClassLoader.loadClass方法和 * ClassLoader.getResource方法. 但ClassFinder总是首先尝试从 * Thread.getContextClassLoader()方法取得ClassLoader * 中并装入类和资源. 这种方法避免了在多级ClassLoader的情况下, 找不到类或资源的情况. *

*

* 假设有如下情况: *

*
    *
  • 工具类A是从系统ClassLoader装入的(classpath)
  • *
  • B是Web Application中的一个类, 是由servlet引擎的 * ClassLoader动态装入的
  • *
  • 资源文件C.properties也在Web Application中, 只有servlet引擎的动态 * ClassLoader可以找到它
  • *
  • B调用工具类A的方法, 希望通过类A取得资源文件 * C.properties
  • *
*

* 如果类A使用 * getClass().getClassLoader().getResource("C.properties") * , 就会失败, 因为系统ClassLoader不能找到此资源. * 但类A可以使用ClassFinder.getResource("C.properties"), 就可以找到这个资源, * 因为ClassFinder调用Thread.currentThead().getContextClassLoader() * 取得了servlet引擎的ClassLoader, 从而找到了这个资源文件. *

*

* 注意, Thread.getContextClassLoader()是在JDK1.2之后才有的, 对于低版本的JDK, * ClassFinder的效果和直接调用ClassLoader完全相同. *

* * @author Michael Zhou * @version $Id: ContextClassLoader.java,v 1.1 2003/07/03 07:26:15 baobao Exp $ */ public class ContextClassLoader { /** * JDK1.2以上, 这个变量保存了Thread.getContextClassLoader()方法. * 对于低版本的JDK, 此变量为null. */ private static Method GET_CONTEXT_CLASS_LOADER_METHOD = null; static { try { GET_CONTEXT_CLASS_LOADER_METHOD = Thread.class.getMethod("getContextClassLoader", (Class[]) null); } catch (NoSuchMethodException e) { // JDK 1.2以下. } } /** *

* 从ClassLoader取得所有resource URL. 按如下顺序查找: *

*
    *
  1. 在当前线程的ClassLoader中查找.
  2. *
  3. 在装入自己的ClassLoader中查找.
  4. *
  5. 通过ClassLoader.getSystemResource方法查找.
  6. *
* * @param resourceName 要查找的资源名, 就是以"/"分隔的标识符字符串 * @return resource的URL数组, 如果没找到, 则返回空数组. 数组中保证不包含重复的URL. */ public static URL[] getResources(String resourceName) { ClassLoader classLoader = null; Set urlSet = new ArrayHashSet(); boolean found = false; // 首先试着从当前线程的ClassLoader中查找. found = getResources(urlSet, resourceName, getClassLoader(), false); // 如果没找到, 试着从装入自己的ClassLoader中查找. if (!found) { getResources(urlSet, resourceName, ContextClassLoader.class.getClassLoader(), false); } // 最后的尝试: 在系统ClassLoader中查找(JDK1.2以上), // 或者在JDK的内部ClassLoader中查找(JDK1.2以下). if (!found) { getResources(urlSet, resourceName, null, true); } if (found) { return (URL[]) urlSet.toArray(new URL[urlSet.size()]); } return new URL[0]; } /** * 在指定class loader中查找指定名称的resource, 把所有找到的resource的URL放入指定的集合中. * * @param urlSet 存放resource URL的集合 * @param resourceName 资源名 * @param classLoader 类装入器 * @param sysClassLoader 是否用system class loader装载资源 * @return 如果找到, 则返回true */ private static boolean getResources(Set urlSet, String resourceName, ClassLoader classLoader, boolean sysClassLoader) { Enumeration i = null; try { if (classLoader != null) { i = classLoader.getResources(resourceName); } else if (sysClassLoader) { i = ClassLoader.getSystemResources(resourceName); } } catch (IOException e) { } if (i != null && i.hasMoreElements()) { while (i.hasMoreElements()) { urlSet.add(i.nextElement()); } return true; } return false; } /** *

* 从ClassLoader取得resource URL. 按如下顺序查找: *

*
    *
  1. 在当前线程的ClassLoader中查找.
  2. *
  3. 在装入自己的ClassLoader中查找.
  4. *
  5. 通过ClassLoader.getSystemResource方法查找.
  6. *
* * @param resourceName 要查找的资源名, 就是以"/"分隔的标识符字符串 * @return resource的URL */ public static URL getResource(String resourceName) { ClassLoader classLoader = null; URL url = null; // 首先试着从当前线程的ClassLoader中查找. classLoader = getClassLoader(); if (classLoader != null) { url = classLoader.getResource(resourceName); if (url != null) { return url; } } // 如果没找到, 试着从装入自己的ClassLoader中查找. classLoader = ContextClassLoader.class.getClassLoader(); if (classLoader != null) { url = classLoader.getResource(resourceName); if (url != null) { return url; } } // 最后的尝试: 在系统ClassLoader中查找(JDK1.2以上), // 或者在JDK的内部ClassLoader中查找(JDK1.2以下). return ClassLoader.getSystemResource(resourceName); } /** * 从ClassLoader取得resource的输入流. 相当于 * getResource(resourceName).openStream(). * * @param resourceName 要查找的资源名, 就是以"/"分隔的标识符字符串 * @return resource的输入流 */ public static InputStream getResourceAsStream(String resourceName) { URL url = getResource(resourceName); try { if (url != null) { return url.openStream(); } } catch (IOException e) { // 打开URL失败. } return null; } /** * 从当前线程的ClassLoader装入类. 对于JDK1.2以下, 则相当于 * Class.forName. * * @param className 要装入的类名 * @return 已装入的类 * @throws ClassNotFoundException 如果类没找到 */ public static Class loadClass(String className) throws ClassNotFoundException { return loadClass(className, true, null); } /** * 从指定的ClassLoader中装入类. 如果未指定ClassLoader, 则从当前线程的 * ClassLoader中装入. * * @param className 要装入的类名 * @param initialize 是否要初始化类 * @param classLoader 从指定的ClassLoader中装入类 * @return 已装入的类 * @throws ClassNotFoundException 如果类没找到 */ public static Class loadClass(String className, boolean initialize, ClassLoader classLoader) throws ClassNotFoundException { if (classLoader == null) { classLoader = getClassLoader(); } return Class.forName(className, initialize, classLoader); } /** * 取得当前线程的ClassLoader. 这个功能需要JDK1.2或更高版本的JDK的支持. * * @return 如果JDK是1.2以前版本, 返回null. 否则返回当前线程的ClassLoader. */ public static ClassLoader getClassLoader() { if (GET_CONTEXT_CLASS_LOADER_METHOD != null) { try { return (ClassLoader) GET_CONTEXT_CLASS_LOADER_METHOD.invoke(Thread.currentThread(), (Object[]) null); } catch (Throwable e) { return null; } } return null; } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy