2013-09-11 3 views
4

У меня есть ситуация, когда я делю одноэлемент между моим кодом, который запускает встроенный сервер и мое веб-приложение. У меня война с классами и инструментом развертывания. Когда я печатаю экземпляры, я вижу:Singleton на самом деле не синглтон

[email protected] 
[email protected] 

Так что это не одиночный. Как это работает?


Мой сервер запуска Jetty код:

public static void main(String[] args) throws Exception 
{ 
    System.out.println(MySingleton.getInstance()); 
    // start Jetty here and deploy war with WebAppContext() 
} 

Мой ServletContextListener сторона код:

public class AppServletContextListener implements ServletContextListener{ 
    @Override 
    public void contextInitialized(ServletContextEvent arg0) { 
     System.out.println(MySingleton.getInstance()); 
    } 
} 

Мой синглтон:

public class MySingleton { 
    private static MySingleton INSTANCE = new MySingleton(); 
    private MySingleton() {} 
    public static MySingleton getInstance() { 
     return INSTANCE; 
    } 
} 

Я вынужден исключить внутри конструктора. Похоже, я получаю два разных.

java.lang.Exception 
     at api.MySingleton.<init>(MySingleton.java:33) 
     at api.MySingleton.<clinit>(MySingleton.java:22) 
     at my.project.StartJetty.main(StartJetty.java:41) 
java.lang.Exception 
     at api.MySingleton.<init>(MySingleton.java:33) 
     at api.MySingleton.<clinit>(MySingleton.java:22) 
     at api.AppServletContextListener.contextInitialized(AppServletContextListener.java:25) 
     at org.eclipse.jetty.server.handler.ContextHandler.startContext(ContextHandler.java:640) 
     at org.eclipse.jetty.servlet.ServletContextHandler.startContext(ServletContextHandler.java:229) 
     at org.eclipse.jetty.webapp.WebAppContext.startContext(WebAppContext.java:1208) 
     at org.eclipse.jetty.server.handler.ContextHandler.doStart(ContextHandler.java:586) 
     at org.eclipse.jetty.webapp.WebAppContext.doStart(WebAppContext.java:449) 
     at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:58) 
     at org.eclipse.jetty.server.handler.HandlerCollection.doStart(HandlerCollection.java:224) 
     at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:58) 
     at org.eclipse.jetty.server.handler.HandlerWrapper.doStart(HandlerWrapper.java:89) 
     at org.eclipse.jetty.server.Server.doStart(Server.java:258) 
     at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:58) 
     at my.project.StartJetty.main(StartJetty.java:66) 
+2

Вы не оставили ни одного кода. – chrylis

+0

минут пожалуйста. – flyer

+0

Singleton - это шаблон, предполагающий, что он выполнен правильно, у вас будет только один объект в памяти, но это не значит, что вы не можете изменить состояние объекта. Всякий раз, когда вы меняете состояние объекта, в зависимости от реализации hashcode()/equals() эти числа будут меняться. – kosa

ответ

5

Посмотрите на какой-то Jetty documentation. Вы можете играть с конфигурациями загрузки классов.

Если установлено значение истинно, то Jetty использует обычный приоритет JavaSE загрузки классов, и отдает приоритет родителей/системы загрузчиком классов. Это позволяет избежать проблем с выпуском нескольких версий класса внутри webapp, но версия , которую предоставляет родительский/системный загрузчик, должна быть правильной версией для всех настраиваемых вами веб-конфигураций.

Это именно то, что вы описываете. Один экземпляр MySingleton загружается основной программой Java, а другой загружается загрузчиком классов Jetty.

+0

Это поведение для некоторых целей, и я должен ожидать этого с другими серверами? – flyer

+0

Для контейнеров сервлетов другого способа сделать не нужно, так как вам нужно загрузить 'war's. На других серверах вы не будете контролировать 'main()', чтобы не беспокоиться. Если вы дважды попытались выполнить 'MySingleton.getInstance()' дважды в слушателе, вы получите тот же экземпляр. То же самое, если вы сделали это в сервлете или другом классе в этом контексте. –

+0

Точно такой же наблюдаемый. Если я использую 'MySingleton' в ресурсах ServletContextListener и REST, это тот же самый экземпляр. – flyer

2

Печать трассировки стека в конструкторе должна предоставить вам информацию, необходимую для выяснения, где она создается и какой порядок. Шаблон Singleton - опасная вещь, обычно лучше сделать это по-другому.

+0

Я обновил вопрос. Хороший намек. – flyer

2

Ваш ServletContextListener и основные классы загружаются различными загрузчиками классов. Всякий раз, когда класс загружается, его статический блок будет выполнен. так что вы получите два экземпляра ...

Если вы хотите, чтобы убедиться, что тот же загрузчик классов загружает синглтон, вы должны указать загрузчик классов самостоятельно.

проверить эту ссылку для получения более подробной информации http://www.javaworld.com/article/2073352/core-java/simply-singleton.html?page=2

Смежные вопросы