我正在使用一个Java应用程序服务器(Smartfox),它可以运行多个应用程序(“扩展”)但是有一个非常不方便的类路径设置,以及它在尝试使用时的问题SLF4J。
要解决这个问题,我想将我的应用程序包装在自己的类加载器中。这样一个包含类的加载器应该像Tomcat一样,因为它
是否有某个库有这样的类加载器我可以在项目中“拖放”?如果没有,自己创建它会难吗?任何已知的陷阱?
答案 0 :(得分:3)
答案 1 :(得分:3)
由于我在嵌入OSGi容器时遇到了麻烦,而且确实有点矫枉过正,所以我推出了自己的解决方案。但有一天我会学习使用OSGi,在这种情况下我不需要嵌入框架。
如果您碰巧想要使用此代码,那么它就是“随心所欲”的许可证。
public class SmartfoxExtensionContainer extends AbstractExtension {
private AbstractExtension extension;
private void initRealExtension() {
final String zone = this.getOwnerZone();
System.out.println("[SmartfoxExtensionContainer] ========= Init extension for zone " + zone + " =========");
try {
// load properties
File propFile = new File("wext/" + zone + ".properties");
System.out.println("[SmartfoxExtensionContainer] Load config from " + propFile.getCanonicalPath());
Properties props = new Properties();
final FileInputStream ins = new FileInputStream(propFile);
try {
props.load(new InputStreamReader(ins, "UTF-8"));
} finally {
try {
ins.close();
} catch (IOException e) {}
}
// construct classloader
File jarDir = new File(props.getProperty("classpath", "wext/" + zone));
System.out.println("[SmartfoxExtensionContainer] Load classes from " + jarDir.getCanonicalPath());
if (!jarDir.isDirectory()) throw new RuntimeException("That is not an existing directory");
final File[] fs = jarDir.listFiles();
URL[] urls = new URL[fs.length];
for (int f = 0; f < fs.length; f++) {
System.out.println("[SmartfoxExtensionContainer] " + fs[f].getName());
urls[f] = fs[f].toURI().toURL();
}
SelfishClassLoader cl = new SelfishClassLoader(urls, SmartfoxExtensionContainer.class.getClassLoader());
// get real extension class
String mainClass = props.getProperty("mainClass", "Extension");
System.out.println("[SmartfoxExtensionContainer] Main class: " + mainClass);
@SuppressWarnings("unchecked")
Class<? extends AbstractExtension> extClass = (Class<? extends AbstractExtension>) cl.loadClass(mainClass);
// create extension and copy settings
extension = extClass.newInstance();
extension.setOwner(this.getOwnerZone(), this.getOwnerRoom());
} catch (Exception e) {
throw new RuntimeException(e);
}
}
/* ======================= DELEGATES ======================= */
@Override
public void init() {
initRealExtension();
extension.init();
}
@Override
public void destroy() {
extension.destroy();
}
@Override
public void handleRequest(String arg0, ActionscriptObject arg1, User arg2, int arg3) {
extension.handleRequest(arg0, arg1, arg2, arg3);
}
@Override
public void handleRequest(String arg0, String[] arg1, User arg2, int arg3) {
extension.handleRequest(arg0, arg1, arg2, arg3);
}
@Override
public void handleInternalEvent(InternalEventObject arg0) {
extension.handleInternalEvent(arg0);
}
@Override
public Object handleInternalRequest(Object params) {
return extension.handleInternalRequest(params);
}
@Override
public void handleRequest(String cmd, JSONObject jso, User u, int fromRoom) {
extension.handleRequest(cmd, jso, u, fromRoom);
}
/* ======================= CUSTOM CLASSLOADER ======================= */
private static class SelfishClassLoader extends URLClassLoader {
SelfishClassLoader(URL[] urls, ClassLoader parent) {
super(urls, parent);
}
// override default behaviour: find classes in local path first, then parent
@Override protected synchronized Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
// First, check if the class has already been loaded
Class<?> clz = findLoadedClass(name);
if (clz == null) {
try {
clz = findClass(name);
} catch (ClassNotFoundException e) {
// ClassNotFoundException thrown if class not found
// from current class loader
}
if (clz == null) {
// If still not found, then invoke parent.findClass in order
// to find the class.
clz = getParent().loadClass(name);
}
}
if (resolve) {
resolveClass(clz);
}
return clz;
};
}
}