简体   繁体   English

如何使现有的Java类/接口实现单例?

[英]How can I make an existing Java class/interface implementation a singleton?

Suppose I am using an ApplicationContext implementation in Spring. 假设我在Spring中使用ApplicationContext实现。

ApplicationContext is an interface in the Java Spring Framework and I cannot change it. ApplicationContext是Java Spring Framework中的接口,我无法更改它。

How do I ensure that there can be only one instance of this implementation? 如何确保该实现只能有一个实例?

For eg. 例如。 I have the following code - 我有以下代码-

public class ApplicationContextSingleton 
{
     private static ApplicationContext context;
     private static int numberOfInstances = 0;

     public static ApplicationContext getApplicationContext()
     {
         if(numberOfInstances == 0)
         {
             context = new ClassPathXmlApplicationContext("spring.xml");
             numberOfInstances++;
         }
         return context;
     }
}

This way, I can ensure that there is only one instance of ApplicationContext, provided it is obtained as follows - 这样,我可以确保只有一个ApplicationContext实例,条件是按以下方式获得它:

ApplicationContext context = ApplicationContextSingleton.getApplicationContext();

But that doesn't stop another programmer from saying - 但这并不能阻止其他程序员说-

ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml"); 

thereby creating a new ApplicationContext. 从而创建一个新的ApplicationContext。 How to prevent this from occuring? 如何防止这种情况发生?

You want to make ApplicationContext a singleton, so I'd override the class with my own custom class, make sure it appears first on the class path, and make it have a private constructor. 您希望将ApplicationContext设为单例,因此我用自己的自定义类覆盖了该类,确保它首先出现在类路径上,并使其具有私有构造函数。

That is, if you're dead set on making it a singleton. 也就是说,如果您不愿意将其设置为单例。 There are better ways to solve your problem, as pointed out by other answers and comments. 正如其他答案和评论所指出的那样,还有更好的方法可以解决您的问题。

Should note that it's usually a bad idea to override pieces of libraries, as it can be the cause of headaches later, especially when you try upgrading your framework version. 应该注意的是,覆盖库片段通常不是一个好主意,因为这可能会在以后引起麻烦,尤其是当您尝试升级框架版本时。

Unless somebody can come up with something reeeeeally creative, I don't think there's a way to do this. 除非有人能提出一些新颖的创意,否则我认为没有办法。 This would be similar to trying to make an int a singleton. 这类似于尝试将int单例化。 Just not gonna happen, as you don't have any control over the usage of classes you didn't write. 只是不会发生,因为您无法控制未编写的类的使用。 You're just going to have to trust your developers not to create a second context. 您将只需要信任您的开发人员就不会创建第二个上下文。

Alternatively, and I can almost promise this will be out of the question, but you could get the full source for spring, make some code changes to make the context a singleton, and then build it out yourself. 另外,我几乎可以保证这是不可能的 ,但是您可以获取spring的完整源代码,进行一些代码更改以使上下文成为单例,然后自行构建。 Not a likely solution, but I felt the need to point it out anyway. 不太可能的解决方案,但是我觉得还是需要指出来。

there is no way to do that because 之所以无法这样做,是因为

ClassPathXmlApplicationContext is not implemented as Singleton pattern by Spring. Spring并未将ClassPathXmlApplicationContext实现为Singleton模式。 Inform every one that you have a utility method to access the context object and creating context using new is expensive. 通知每个人您都有一种实用方法来访问上下文对象,并且使用new创建上下文非常昂贵。

  1. Use an automated build system that builds your code whenever it is committed to your software repository. 使用自动构建系统,该系统在将代码提交到您的软件存储库时就可以生成您的代码。
  2. Integrate tools into your build process like FindBugs or PMD. 将工具(例如FindBugs或PMD)集成到您的构建过程中。 If these tools trigger certain conditions, fail the build and allow no artifacts to be generated. 如果这些工具触发了某些条件,则使构建失败并不允许生成任何工件。
  3. Create a case in your integrated tool that looks for developers creating their own context. 在集成工具中创建一个案例,以寻找开发人员创建自己的上下文。

So you can't stop them from doing it, but you can stop them from pushing such things into your dev, qa, and prod environments. 因此,您不能阻止他们这样做,但是可以阻止他们将这些事情推送到您的开发,质量保证和产品环境中。 This might seem like overkill, but this sort of process will help with hundreds of things your developers -can- do but shouldn't. 这似乎有些过分,但是这种过程将帮助开发人员完成数百项但不应该做的事情。

Josh Block suggests using an enum in Effective Java . Josh Block建议在有效Java中使用枚举。 This isnt a link to that book , but it shows his and the older way (alternative) way of doing it 这不是到该书的链接 ,但它显示了他和较旧的(替代)方法

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM