【问题标题】:Java - Singleton usage with multiple class loadersJava - 使用多个类加载器的单例使用
【发布时间】:2016-09-17 05:07:09
【问题描述】:

我在 Java 中有一个简单的单例类,如下所示:

public class Singleton{
    private static Singleton instance;

    private Singleton(){}

    public static Singleton getInstance(){
        if (instance == null){
            instance = new Singleton();
        }
        return instance;
    }

    public void doSomething(){
        ...
    }
}

我的代码还包含两个类,从现在开始称为 A 和 B,它们都具有以下结构:

public class Foo{
    ...
    public void bar(){
        ...
        Singleton.getInstance().doSomething();
        ...
    }
    ...
}

在执行期间,类 A 中的代码首先执行,因此它静默地实例化单例实例。但是,稍后当 B 的代码被执行时,单例实例又被实例化了,这不是我想要实现的。

经过一番调查,我们发现 A 类和 B 类使用了不同的类加载器,这意味着单例类也被加载了两次,从而产生了两个单例实例。

我已经在网上寻找解决此问题的方法,并找到了几个(非常相似的)页面,例如http://www.javaworld.com/article/2073352/core-java/simply-singleton.html?page=2http://snehaprashant.blogspot.nl/2009/01/singleton-pattern-in-java.html

但是,在尝试了几个选项后,我仍然无法让它工作,主要是因为我真的不知道如何在上面列出的简单代码中应用解决方案。

所以我的问题是:有人可以为我的代码提供一个实用的解决方案来解决上述问题,以便无论使用何种类加载器,单例都只实例化一次?

【问题讨论】:

  • @OldCurmudgeon 是的,这个答案基本上指向上面页面链接中也描述的解决方案。但是,我不知道要使用该方法以及需要进行哪些其他更改才能使其正常工作。
  • 为什么还要使用不同的类加载器——应用服务器环境?
  • 是的,这段代码是在CloverETL环境中使用的,显然使用了不同的类加载器

标签: java singleton classloader


【解决方案1】:

我怀疑 JavaWorld 文章中的解决方案是否有效。 getContextClassLoader()Singleton.class.getClassLoader() 每次可以返回不同的类加载器。如果你有一个一致的类加载器,那么使用这个类的唯一方法就是通过反射。

我猜他们希望你替换:

Singleton.getInstance().doSomething();

与:

try {
    Object instance = getClass("package.Singleton").getMethod("getInstance").invoke(null);
    instance.getClass().getMethod("doSomething").invoke(instance);
} catch (ReflectiveOperationException e) {
    e.printStackTrace();
}

相反,我会看看为什么有多个类加载器。要么将所有代码保存在同一个类加载器下,要么将单例放入两个类加载器的共同父类中,并使该类对子类加载器不可用。

【讨论】:

  • 感谢您的回答!我刚刚尝试过这个解决方案,正如您已经想到的那样:它不起作用,因为它仍然会导致多个单例实例。代码在 CloverETL 环境中运行,所以我会问他们为什么要使用多个类加载器以及他们是否有解决方案。
  • 多个类加载器的一个原因是 OSGI 环境,每个包都有自己的类加载器。在 OSGI 中,这是一件好事和可取的事情。但是会导致类似这样的问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-04-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多