在OSGi環境中,在Bundle內部代碼中要得到自己Bundle的ClassLoader就很簡單,在自己Bundle的代碼中,直接寫this.getClass().getClassLoader()就得到了自己Bundle的ClassLoader了。但怎么在其他Bundle或外部代碼中得到任意一個Bundle的ClassLoader呢?Bundle和BundleContext都沒有提供getClassLoader方法來獲取,我就用了一種比較另類的方法來獲取。突破口就在Bundle.loadClass(String className)方法,目前此方法已經在QuickWebFramework中應用了。
思路:
1.調用Bundle的findEntries方法,得到Bundle中任意一個class文件。
2.根據這個class文件的路徑,得到類名
3.調用Bundle的loadClass方法,得到這個類
4.調用這個類的getClassLoader方法,得到ClassLoader
PS:
1.由上面的思路可知此方法不能用於沒有一個Java類的Bundle
2.OSGi系統Bundle(即ID為0的Bundle)得不到class文件,所以此方法不能用於OSGi系統Bundle
代碼如下:
import java.net.URL; import java.util.Enumeration; import org.osgi.framework.Bundle; /** * 插件輔助類 * 作者博客:http://www.cnblogs.com/aaaSoft * @author aaa * */ public class BundleUtils { /** * 得到Bundle的類加載器 * * @param bundle * @return */ public static ClassLoader getBundleClassLoader(Bundle bundle) { // 搜索Bundle中所有的class文件 Enumeration<URL> classFileEntries = bundle.findEntries("/", "*.class", true); if (classFileEntries == null || !classFileEntries.hasMoreElements()) { throw new RuntimeException(String.format("Bundle[%s]中沒有一個Java類!", bundle.getSymbolicName())); } // 得到其中的一個類文件的URL URL url = classFileEntries.nextElement(); // 得到路徑信息 String bundleOneClassName = url.getPath(); // 將"/"替換為".",得到類名稱 bundleOneClassName = bundleOneClassName.replace("/", ".").substring(0, bundleOneClassName.lastIndexOf(".")); // 如果類名以"."開頭,則移除這個點 while (bundleOneClassName.startsWith(".")) { bundleOneClassName = bundleOneClassName.substring(1); } Class<?> bundleOneClass = null; try { // 讓Bundle加載這個類 bundleOneClass = bundle.loadClass(bundleOneClassName); } catch (ClassNotFoundException e) { throw new RuntimeException(e); } // 得到Bundle的ClassLoader return bundleOneClass.getClassLoader(); } }