Как синглтоны обрабатываются в веб-приложении?
Из того, что я понимаю, синглтон в основном, когда у вас есть частный член, который представляет объект, для которого вы хотите иметь один экземпляр. Затем в конструкторе вы инициализируете объект-член.
Все ссылки для этого объекта выполняются через общедоступное свойство, а публичное свойство просто ссылается на закрытый член, который уже был создан.
Теперь в веб-приложении, как это работает? Один экземпляр просто держится в контейнере (скажем, tomcat), пока tomcat не завершит работу?
Ответы
Ответ 1
Если ваша среда исполнения использует несколько загрузчиков классов, вы получаете один синглтон на экземпляр вашего класса. Если ваш однопользовательский класс загружается в разные загрузчики классов, то на самом деле это два разных класса, а затем будут два экземпляра "singleton".
В документации вы можете найти информацию о загрузчиках классов Tomcat.
Ответ 2
Следует различать шаблон Singleton и его реализацию. Большинство, если не все распространенные реализации Singleton, страдают от упомянутых проблем с загрузкой классов, а также сериализации, безопасности потоков и т.д. См. https://www.securecoding.cert.org/confluence/display/java/MSC07-J.+Prevent+multiple+instantiations+of+singleton+objects для довольно тщательный обзор.
Однако шаблон Singleton в самом широком смысле может быть любой гарантированной гарантией в определенном контексте. Уникальность Singleton может быть указана только относительно данной области, такой как загрузчик классов, JVM, контейнер или кластер; уровень уникальности зависит от реализации, которую следует выбирать на основе требований приложения.
Два очень распространенных требования, которые приводят к использованию синглтонов, - это инъекция зависимостей (c.q. с использованием factory) и кэширование в памяти. В обоих случаях есть хорошие рамки, которые скрывают аспект Singleton от клиента и обеспечивают достаточный уровень уникальности внутри, например, контейнера корпоративного приложения. Для инъекций зависимостей Spring на ум приходит Guice или Pico. Для кэширования я знаю, что Ehcache является ведущим решением, но, безусловно, там больше. (забавные мелочи: имя "ehcache" - палиндром)
В общем, использование синглтонов "нахмурилось" и рассматривается как анти-шаблон. С другой стороны, услуги, такие как инъекция и кэширование зависимостей, требуют уникальности для работы. Поэтому мы немного обманываем себя, если объявляем анти-синглтон и в то же время используем Spring или Ehcache или тому подобное.
Страх перед Синглтонами, на мой взгляд, связан с многочисленными плохими реализациями, которые возможны и многочисленны. И даже если сама реализация Singleton "безопасна", вызов ее напрямую (через статический доступ) во всем приложении приводит к жесткой связи и плохой проверке.
Улучшение, которое вы можете сделать, если у вас есть Singleton factory в вашем приложении, заключается в реорганизации его клиентов, чтобы они не вызывали factory, когда им нужна зависимость, но предоставляют частное поле и общедоступную сеттер, позволяющий вводить зависимость. Затем вы можете централизовать инициализацию клиентов, возможно, в том же factory, и оставить код клиента чистым, слабо связанным и тестируемым (теперь вы можете вводить макетные зависимости). Это также может быть первым шагом к внедрению каркаса инъекции зависимостей, такого как Spring.
Я надеюсь, что где-то в этой довольно длинной и бессвязной должности я помог ответить на ваш вопрос! (-;
Ответ 3
Теперь в веб-приложении, как это работает? Один экземпляр просто держится в контейнере (скажем, tomcat), пока tomcat не завершит работу?
@Greg ответ объясняет, что могут быть разные экземпляры одноэлементного класса (фактически разные классы с точки зрения JVM), если каждый контейнер webapp в TomCat имеет свой собственный загрузчик классов.
В любом случае, время жизни (GC) одиночного тока будет временем жизни соответствующих загрузчиков классов. На практике, однако, легко ссылаться на загрузчик классов, что приводит к проживанию синглтона до выхода JVM.
Это одна из причин, по которой обычные синглтоны проблематичны в веб-приложениях. Лучше использовать экземпляры с контейнером; например как поддерживается Spring и другими структурами IoC.
Ответ 4
Да, есть одноэлементный шаблон, который работает, как вы описываете. Это проблематично и поставляется с предостережениями, как упомянуто выше Стивеном С. Если вам нужны данные одного экземпляра, лучшим вариантом является создание его контейнером spring (или других контейнеров, которые его поддерживают), которые будут обрабатывать экземпляр (что гораздо более проблематично, чем вы могли бы подумать).
Если вы должны сворачивать самостоятельно, внимательно изучите двунаправленную блокировку идиомы и проблемы, возникающие с ней, чтобы понять проблемы, которые могут возникнуть при создании экземпляра oneton. Если ваше инстанцирование нетривиально, на самом деле очень легко получить несколько экземпляров или условия гонки в инстанцировании. Я сделал это сам. В производстве (но это было давно;))