public class ServiceClassloader extends URLClassLoader { private static final ConcurrentHashMap<String, Class<?>> classCacheMap = new ConcurrentHashMap<String, Class<?>>(); private final URL[] urls; public ServiceClassloader(URL[] urls, ClassLoader parent) { super(urls, parent); this.urls = urls; init(); } private void init() { for (URL url : urls) { initClassName(url); } } private void initClassName(URL url) { String path = url.getPath(); try { JarFile jarFile = new JarFile(path); Enumeration<JarEntry> entries = jarFile.entries(); while(entries.hasMoreElements()) { JarEntry entry = entries.nextElement(); String classFileName = entry.getName(); if (classFileName.endsWith(".class")) { classFileName = classFileName.replace("/", "."); String className = classFileName.substring(0, classFileName.lastIndexOf(".")); loadClass(className); } } } catch (Exception e) { e.printStackTrace(); } } @Override public Class<?> loadClass(String name) throws ClassNotFoundException { Class<?> clazz = classCacheMap.get(name); if (clazz == null) { clazz = super.loadClass(name); classCacheMap.put(name, clazz); } return clazz; } }
public class SpringClassLoader extends ClassLoader { private ServiceClassloader serviceClassloader; public ServiceClassloader getServiceClassLoader() { return serviceClassloader; } public void setServiceClassLoader(ServiceClassloader serviceClassLoader) { this.serviceClassloader = serviceClassLoader; } /** * 定義加載器的加載規則 * 1)先從SystemClassLoader進行加載指定的名字的class * 2)未找到,則用自定義的ServiceClassLoader加載指定路徑下的jar中的class * @param name 預加載的class名稱 * @return 加載完的Class * @throws ClassNotFoundException */ @Override public Class<?> loadClass(String name) throws ClassNotFoundException { // first load classPath, then load third Libs; try { Class<?> clazz = loadClasspathClass(name); if (clazz != null) { return clazz; } clazz = loadThirdLibsClass(name); if (clazz != null) { return clazz; } } catch (Exception e) { e.printStackTrace(); } throw new ClassNotFoundException(name); } /** * 經過SystemClassLoader進行加載指定名字的class * @param name * @return */ private Class<?> loadClasspathClass(String name) { try { return super.loadClass(name); } catch (Exception e) { e.printStackTrace(); } return null; } /** * 經過自定義的ServiceClassLoader加載系統路徑上jar文件指定名字class * @param name * @return */ private Class<?> loadThirdLibsClass(String name) { try { return serviceClassloader.loadClass(name); } catch (Exception e) { e.printStackTrace(); } return null; } }