forked from datageartech/datagear
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[connection]完善数据库驱动类加载器,避免驱动本身的资源、类代理至父类加载器加载
- Loading branch information
1 parent
f1d37ab
commit a9b0294
Showing
1 changed file
with
108 additions
and
83 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -26,7 +26,10 @@ | |
/** | ||
* 指定路径的驱动类加载器。 | ||
* <p> | ||
* 注意:此类会优先从指定路径中加载类,因此,不应该将标准库放入此路径中。 | ||
* 注意:对于非JDK自带的类,此类加载器仅会从{@linkplain #getPath()}加载,而不会代理给父类加载器。 | ||
* </p> | ||
* <p> | ||
* 此规则可以避免驱动类依赖的某些库在{@linkplain #getPath()}中找不到时代理至应用类加载器,而可能出现版本不一致的情况。 | ||
* </p> | ||
* | ||
* @author [email protected] | ||
|
@@ -83,85 +86,89 @@ public void setOutsideForceLoads(Set<String> outsideForceLoads) | |
@Override | ||
public URL getResource(String name) | ||
{ | ||
if (LOGGER.isDebugEnabled()) | ||
LOGGER.debug("start getting resource URL for [" + name + "]"); | ||
|
||
URL url = findResource(name); | ||
|
||
if (url == null) | ||
{ | ||
ClassLoader parent = getParentClassLoader(); | ||
|
||
if (LOGGER.isDebugEnabled()) | ||
LOGGER.debug("delegate parent class loader for getting resource URL for [" + name + "]"); | ||
|
||
return parent.getResource(name); | ||
} | ||
// 对于独立的驱动程序类加载器,不应该代理至父类加载器 | ||
// if (url == null) | ||
// { | ||
// ClassLoader parent = getParentClassLoader(); | ||
// | ||
// if (LOGGER.isDebugEnabled()) | ||
// LOGGER.debug("delegate parent class loader for getting resource URL for [" + name + "]"); | ||
// | ||
// return parent.getResource(name); | ||
// } | ||
|
||
if (LOGGER.isDebugEnabled()) | ||
LOGGER.debug("got resource URL [" + url + "] for [" + name + "] in path [" + getPath() + "]"); | ||
LOGGER.debug("getResource [" + url + "] for [" + name + "] in path [" + getPath() + "]"); | ||
|
||
return url; | ||
} | ||
|
||
@Override | ||
public Enumeration<URL> getResources(String name) throws IOException | ||
{ | ||
if (LOGGER.isDebugEnabled()) | ||
LOGGER.debug("start getting resource URLs for [" + name + "]"); | ||
|
||
Enumeration<URL> urls = findResources(name); | ||
|
||
if (urls == null || urls.hasMoreElements()) | ||
{ | ||
ClassLoader parent = getParentClassLoader(); | ||
|
||
if (LOGGER.isDebugEnabled()) | ||
LOGGER.debug("delegate parent class loader for getting resource URLs for [" + name + "]"); | ||
|
||
return parent.getResources(name); | ||
} | ||
// 对于独立的驱动程序类加载器,不应该代理至父类加载器 | ||
// if (urls == null || urls.hasMoreElements()) | ||
// { | ||
// ClassLoader parent = getParentClassLoader(); | ||
// | ||
// if (LOGGER.isDebugEnabled()) | ||
// LOGGER.debug("delegate parent class loader for getting resource URLs for [" + name + "]"); | ||
// | ||
// return parent.getResources(name); | ||
// } | ||
|
||
if (LOGGER.isDebugEnabled()) | ||
LOGGER.debug("got resource URLs for [" + name + "] in path [" + getPath() + "]"); | ||
LOGGER.debug("getResources for [" + name + "] in path [" + getPath() + "]"); | ||
|
||
return urls; | ||
} | ||
|
||
@Override | ||
public InputStream getResourceAsStream(String name) | ||
{ | ||
if (LOGGER.isDebugEnabled()) | ||
LOGGER.debug("start getting resource as stream for [" + name + "]"); | ||
|
||
URL url = findResource(name); | ||
|
||
if (url == null) | ||
{ | ||
ClassLoader parent = getParentClassLoader(); | ||
// 对于独立的驱动程序类加载器,不应该代理至父类加载器 | ||
// if (url == null) | ||
// { | ||
// ClassLoader parent = getParentClassLoader(); | ||
// | ||
// if (LOGGER.isDebugEnabled()) | ||
// LOGGER.debug("delegate parent class loader for getting resource as stream for [" + name + "]"); | ||
// | ||
// return parent.getResourceAsStream(name); | ||
// } | ||
|
||
if (LOGGER.isDebugEnabled()) | ||
LOGGER.debug("delegate parent class loader for getting resource as stream for [" + name + "]"); | ||
if (url == null) | ||
return null; | ||
|
||
return parent.getResourceAsStream(name); | ||
} | ||
InputStream in = null; | ||
|
||
try | ||
{ | ||
return url.openStream(); | ||
in = url.openStream(); | ||
} | ||
catch (IOException e) | ||
{ | ||
return null; | ||
} | ||
|
||
if (LOGGER.isDebugEnabled()) | ||
LOGGER.debug("getResourceAsStream [" + in + "] for [" + name + "] in path [" + getPath() + "]"); | ||
|
||
return in; | ||
} | ||
|
||
@Override | ||
protected synchronized Class<?> loadClass(String name, boolean resolve) | ||
throws ClassNotFoundException, ClassFormatError | ||
{ | ||
if (LOGGER.isDebugEnabled()) | ||
LOGGER.debug("start loading class [" + name + "]"); | ||
// JDK标准库应由父类加载 | ||
if (isJDKStandardClassName(name)) | ||
return Class.forName(name, resolve, getParentClassLoader()); | ||
|
||
// -拷贝自java.net.URLClassLoader.FactoryURLClassLoader | ||
SecurityManager sm = System.getSecurityManager(); | ||
|
@@ -179,57 +186,48 @@ protected synchronized Class<?> loadClass(String name, boolean resolve) | |
|
||
if (clazz == null) | ||
{ | ||
// 标准库不应在此加载 | ||
if (name.startsWith("java")) | ||
; | ||
else | ||
try | ||
{ | ||
clazz = findClass(name); | ||
} | ||
catch(ClassNotFoundException e) | ||
{ | ||
} | ||
catch(ClassFormatError e) | ||
{ | ||
try | ||
{ | ||
clazz = findClass(name); | ||
} | ||
catch (ClassNotFoundException e) | ||
{ | ||
// 找不到类,则代理给父类加载器 | ||
} | ||
catch (ClassFormatError e) | ||
{ | ||
// 类加载出错(比如版本不兼容),则抛出 | ||
throw e; | ||
} | ||
// 类加载出错(比如版本不兼容),则抛出 | ||
throw e; | ||
} | ||
} | ||
|
||
if (clazz == null) | ||
// 强制在此加载的类 | ||
if (clazz == null && this.outsideForceLoads != null && this.outsideForceLoads.contains(name)) | ||
{ | ||
// 强制在此加载的类 | ||
if (this.outsideForceLoads != null && this.outsideForceLoads.contains(name)) | ||
InputStream in = getParentClassLoader().getResourceAsStream(classNameToPath(name)); | ||
|
||
if (in == null) | ||
throw new ClassNotFoundException(name); | ||
|
||
byte[] bytes = null; | ||
|
||
try | ||
{ | ||
bytes = IOUtil.getBytes(in); | ||
} | ||
catch(IOException e) | ||
{ | ||
throw new ClassNotFoundException(name, e); | ||
} | ||
finally | ||
{ | ||
InputStream in = getResourceAsStream(classNameToPath(name)); | ||
|
||
if (in == null) | ||
throw new ClassNotFoundException(name); | ||
|
||
byte[] bytes = null; | ||
|
||
try | ||
{ | ||
bytes = IOUtil.getBytes(in); | ||
} | ||
catch (IOException e) | ||
{ | ||
throw new ClassNotFoundException(name, e); | ||
} | ||
finally | ||
{ | ||
IOUtil.close(in); | ||
} | ||
|
||
clazz = defineClass(name, bytes, 0, bytes.length); | ||
IOUtil.close(in); | ||
} | ||
|
||
clazz = defineClass(name, bytes, 0, bytes.length); | ||
} | ||
|
||
if (clazz == null) | ||
// 此时仅代理父类加载JDK扩展库,其他都应由此类加载器加载 | ||
if (clazz == null && isJDKExtClassName(name)) | ||
{ | ||
ClassLoader parent = getParentClassLoader(); | ||
|
||
|
@@ -242,9 +240,36 @@ protected synchronized Class<?> loadClass(String name, boolean resolve) | |
if (resolve) | ||
resolveClass(clazz); | ||
|
||
if (LOGGER.isDebugEnabled()) | ||
LOGGER.debug("load class [" + (clazz == null ? "null" : clazz.getName()) + "] for name [" + name | ||
+ "] in path [" + getPath() + "]"); | ||
|
||
return clazz; | ||
} | ||
|
||
/** | ||
* 是否JDK标准类名。 | ||
* | ||
* @param name | ||
* @return | ||
*/ | ||
protected boolean isJDKStandardClassName(String name) | ||
{ | ||
return (name.startsWith("java.") || name.startsWith("javax.")); | ||
} | ||
|
||
/** | ||
* 是否JDK扩展类名。 | ||
* | ||
* @param name | ||
* @return | ||
*/ | ||
protected boolean isJDKExtClassName(String name) | ||
{ | ||
return (name.startsWith("sun.") || name.startsWith("org.ietf.") || name.startsWith("org.omg.") | ||
|| name.startsWith("org.w3c.") || name.startsWith("org.xml.")); | ||
} | ||
|
||
/** | ||
* 获取上级类加载器。 | ||
* | ||
|