简体   繁体   中英

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

Suppose I am using an ApplicationContext implementation in Spring.

ApplicationContext is an interface in the Java Spring Framework and I cannot change it.

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 context = ApplicationContextSingleton.getApplicationContext();

But that doesn't stop another programmer from saying -

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

thereby creating a new 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.

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. 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. 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. Inform every one that you have a utility method to access the context object and creating context using new is expensive.

  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. 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 . This isnt a link to that book , but it shows his and the older way (alternative) way of doing it

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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