【发布时间】:2016-04-24 03:03:18
【问题描述】:
任务和初步调查
我尝试在一个 java swing 应用程序的缓存实例附近设置两个 Oracle Coherence。可以找到解决方案的想法here。我的情况有点复杂,这就是游戏开始的地方。
简短说明
就我而言,有一个帐户服务。它可以有两个端点:SIT 和 UAT。为了创建两个这样的服务,我需要加载 Coherence 的两个“实例”,以便用系统变量 (tangosol.coherence.cacheconfig) 覆盖端点。
我有:
- app的主要代码位于mainapp.jar中;
- 位于 account-interfaces.jar 中的 AccountService 接口;
- AccountServiceImpl 类,位于 account-impl.jar 中并实现 AccountService 接口;
- 我的主要应用程序具有以下结构
bin: startup.bat, startup.sh conf: app.properties lib: mainapp.jar, account-interfaces.jar, account-impl.jar, coherence.jar
尝试的方法
我创建了一个专用的子优先类加载器 - InverseClassLoader,并将 AppLaunchClassLoader(默认的 Thread.currentThread().GetContextClassLoader() 类加载器)设为它的父级。使用 InverseClassLoader 我加载 AccountServiceImpl 类:
Class<AccountServiceImpl> acImplClass = contextClassLoader.selfLoad(AccountServiceImpl.class).loadClass(AccountServiceImpl.class);
Constructor<AccountServiceImpl> acConstructor =
acImplClass .getConstructor(String.class);
AccountService acService = acConstructor .newInstance(serviceURL);
问题和疑问
- 我收到“AccountServiceImpl 无法转换为 AccountService”异常,这意味着这两个类由不同的类加载器加载。 但是那些类加载器是父子关系。所以我是对的,即使一个类是由父类(接口 - '抽象'类型)加载的,它也不能与子类加载器加载的类(具体实现)一起使用?那么为什么我们需要这种父子关系呢?
- 我在代码中指定了 AccountService 接口,它由默认的类加载器加载。我尝试将上面的代码包装为一个线程并将 InverseClassLoader 设置为上下文类加载器。没有改变。那么我不能使用这样的接口实现编码(如通常的编码)并且需要一直使用反射来调用具体方法,这对吗? (希望有解决方案);
- 比如说,我列出了由 InverseClassLoader 加载的 AccountService 和 AccountServiceImpl 类。如果我需要这两个可访问的其他类也由 InverseClassLoader 加载怎么办?有没有办法说所有“相关”类都必须由同一个类加载器加载?
更新
这里是 InverseClassLoader:
public class InvertedClassLoader extends URLClassLoader {
private final Set<String> classesToNotDelegate = new HashSet<>();
public InvertedClassLoader(URL... urls) {
super(urls, Thread.currentThread().getContextClassLoader());
}
public InvertedClassLoader selfLoad(Class<?> classToNotDelegate) {
classesToNotDelegate.add(classToNotDelegate.getName());
return this;
}
@Override
public Class<?> loadClass(String className, boolean resolve) throws ClassNotFoundException {
if (shouldNotDelegate(className)) {
System.out.println("CHILD LOADER: " + className);
Class<?> clazz = findClass(className);
if (resolve) {
resolveClass(clazz);
}
return clazz;
}
else {
System.out.println("PARENT LOADER: " + className);
return super.loadClass(className, resolve);
}
}
public <T> Class<T> loadClass(Class<? extends T> classToLoad) throws ClassNotFoundException {
final Class<?> clazz = loadClass(classToLoad.getName());
@SuppressWarnings("unchecked")
final Class<T> castedClass = (Class<T>) clazz;
return castedClass;
}
private boolean shouldNotDelegate(String className) {
if (classesToNotDelegate.contains(className) || className.contains("tangosol") ) {
return true;
}
return false;
}
【问题讨论】:
-
根据您的代码很难弄清楚。您能否简要描述一下您正在尝试实施的设计理念?
标签: java classloader urlclassloader contextclassloader