【发布时间】:2014-03-06 12:22:55
【问题描述】:
我有一个在公共库中实现一些基本功能的单例对象。它比这复杂得多,但为了记录问题,下面是单例实现,除了一个内部属性/对象之外,所有内部属性/对象都被删除:
package mystuff.lib.common
public class CommonSingleton {
public final static CommonSingleton INSTANCE = new CommonSingleton();
private Cache<String, Object> cache = null;
private CommonSingleton() {
// Exists only to defeat instantiation.
Initialize();
}
private void Initialize() {
cache = null;
}
public Cache<String, Object> getCache() {
if (cache == null) {
cache = new Cache<String, Object>();
}
return cache;
}
public void Reload() {
Initialize();
}
}
我已将该库包含在两个单独的项目中。该库未安装在运行代码的机器上。在 IntelliJ IDEA 中创建工件时,公共库的内容包含在每个 JAR 中。
两个项目(JAR 文件)在父应用程序中加载和运行(作为插件),因此它们都在同一个 JVM 中加载。我希望每个 JAR 都有自己的这个公共单例的副本,因为它们毕竟是单独的 JAR 文件。它只包含在一个公共库中,因为我的许多项目都需要相同的功能,我宁愿将这个库包含在我的项目中,也不愿让代码的多个副本随处可见。
项目/模块 #1:TestPluginOne.JAR
package mystuff.plugins.TestPluginOne;
import mystuff.lib.common.CommonSingleton;
import mystuff.lib.common.Objects.Cache;
public class TestClassOne {
public TestClassOne() {
}
public Boolean SaveItemInCache(String key, String content) {
return CommonSingleton.INSTANCE.getCache().add(key, content, 30);
}
public void Reload() {
CommonSingleton.INSTANCE.Reload();
}
}
项目/模块#2:TestPluginTwo.JAR
package mystuff.plugins.TestPluginTwo;
import mystuff.lib.common.CommonSingleton;
import mystuff.lib.common.Objects.Cache;
public class TestClassTwo {
public TestClassTwo() {
}
public String GetItemFromCache(String key) {
return CommonSingleton.INSTANCE.getCache().get(key);
}
public void Reload() {
CommonSingleton.INSTANCE.Reload();
}
}
然而,我发现当我在两个模块中使用这个对象时(请注意,单独的 JAR 文件),它们都在访问同一个单例。虽然这个带有 Cache 对象的特定示例可能不会表明这有任何问题,但我需要将它们视为单独的对象有很多原因。有许多内部/私有成员变量需要包含不同的值,具体取决于使用此 Singleton 的项目/模块/插件。
我很困惑。当我在 .NET 中(例如)在单独的 DLL 中执行此操作时,每个 DLL 都维护它自己的该公共对象的内部实例。
我怎样才能将这个通用的 Singleton 功能包含在来自通用库的单独项目中,而不共享 Singleton 对象的实例?
谢谢!
【问题讨论】:
-
只是想知道,ThreadLocal 可以在这里工作吗?
ThreadLocal<Singleton>? -
@vikingsteve 我以前没有使用过 ThreadLocal。我对此进行了调查,但我认为它并不真正适用于我的情况。此外,我相信我们的插件运行的宿主应用程序无论如何都是单线程的。
-
当我只有一个插件启动时,架构可以完美运行。第一次访问公用功能时,会传入对父插件对象的引用,以便公用库能够正常运行。我遇到的问题是,当涉及第二个模块(JAR)时,实际的公共对象是共享的,而不仅仅是实现。所以第二个插件传入了对自身的引用,覆盖了第一个插件的初始化。
-
听起来你只需要硬着头皮使用两个不同的单例。
-
是的。但这比这要复杂得多。公共库中定义的所有对象都使用公共单例及其所有对象。当插件启动时,我将插件的一个实例传递给公共单例,然后从任何公共库函数中引用该实例。现在我发现每个插件之间的公共单例实例之间没有隔离,我将不得不将插件对象的实例传递给几乎每个公共库函数和/或对象实例化。你能说BARF吗!?!
标签: java jar intellij-idea singleton