Безопасен ли такой дизайн бобов Spring Singleton? - PullRequest
24 голосов
/ 21 июня 2011

Рассмотрим следующий класс Spring Service. Определена область действия пружины Singleton. Два служебных компонента, автоматически подключаемые как поля в приведенном ниже классе, имеют схожую структуру - они также состоят из полей, которые являются следующими из

  • Весенние бобы сами
  • классы без гражданства
  • неизменных классов

и так далее. Этот шаблон в целом используется в дизайне приложения.

@Service     
public class DocumentService {  
  private final DocumentGenerationService documentGenerationService;
  private final DocumentPublishService documentPublishService;

  @Autowired
  public DocumentService (DocumentGenerationService documentGenerationService,    
                          DocumentPublishService documentPublishService) {
  this.documentGenerationService = documentGenerationService;
  this.documentPublishService = documentPublishService;
}

... methods follow

Правильно ли говорить, что класс DocumentService является неизменным, поскольку невозможно изменить любое из двух его полей (которые являются пружинными компонентами, которые могут быть инициализированы только один раз самим контейнером)?

В любом случае, может ли bean-компонент DocumentService, определенный выше, считаться поточно-ориентированным? И если следовать этой схеме, то приложение в целом будет поточно-ориентированным?

Ответы [ 6 ]

20 голосов
/ 29 июня 2011

Правильно ли говорить, что класс DocumentService является неизменным, поскольку невозможно изменить любое из двух его полей (которые являются пружинными компонентами, которые могут быть инициализированы только один раз самим контейнером)?

В соответствии с определением неизменности , и формально говоря, этот класс НЕ является неизменным .

Объект является неизменным, если невозможно изменить состояние объекта, а состояние documentGenerationService и documentPublishService является частью состояния класса DocumentService.

И, как следствие, , если у класса всегда одно и то же состояние, он ведет себя всегда одинаково . Другими словами, нет способа изменить поведение неизменяемого объекта, поскольку поведение объекта зависит только от его состояния, а в неизменяемом объекте это состояние никогда не изменяется (примерами неизменяемых объектов являются строки и целые числа).

Обратите внимание, что в определении неизменяемости мы находим исключение, когда " объект считается неизменным, даже если некоторые [...] атрибуты изменяются, но состояние объекта [и, следовательно, поведение] кажется неизменным [...]", но в этом случае (с предоставленной информацией) изменение состояния ссылок может определенно изменить поведение класса (так как у нас нет никакого контроля на собственное внутреннее состояние).

Существует стратегия , чтобы сделать класс неизменным. Вы уже следуете некоторым из его рекомендаций, но в случае, если вы хотите сделать его неизменным (я думаю, что это не так), вам понадобятся другие, такие как «защитная копия» аргументов, которые вы получите в конструктор и избегают переопределения методов подклассов .

Эта ссылка тоже интересна.

Тем не менее, вы не должны делать бины Spring неизменяемыми, поскольку это не тот способ использования модели программирования, которую предлагает Spring. Таким образом, в данном случае «хорошо», что класс не является неизменным.

В любом случае, может ли bean-компонент DocumentService, как определено выше, считаться поточно-ориентированным?

Как заявлено здесь, этот класс IS потокобезопасен . Многие потоки могут безопасно получить доступ к этому классу без каких-либо условий гонки. Мы не можем сказать то же самое о полях, которые он содержит, но этот класс является потокобезопасным. Это работает точно так же, как и «потокобезопасный список»: он может содержать «нет поточно-безопасных» объектов, но все равно быть «потокобезопасным списком».

А если следовать этой схеме, то приложение в целом будет поточно-ориентированным?

Если все классы вашей системы являются поточно-ориентированными (то есть нигде не появляется ни одного условия гонки), вы можете неофициально сказать, что приложение является поточно-ориентированным.

4 голосов
/ 21 июня 2011

Пружина не гарантирует безопасность резьбы. Это ваша ответственность.

Все личные переменные-члены являются общими. Они могут быть окончательными, но это только означает, что ссылки не могут быть изменены. Любое изменяемое состояние должно быть синхронизировано. Если они действительно неизменны, то я думаю, что вы на твердой почве.

Я согласен с комментарием об зависимостях автопроводки. Я бы оставил их под контролем Спринг, если это возможно.

2 голосов
/ 21 июня 2011

Код примера, показанный в вашем вопросе, определенно ориентирован на многопоточность.

Однако код должен рассматриваться в контексте всего приложения. Например, приведенный выше код не предоставляет никаких гарантий безопасности потоков объектов, на которые ссылаются атрибуты documentGenerationService и documentPublishService. Если они не синхронизированы должным образом, то код, который их использует (включая другие методы этого класса), может быть не поточно-ориентированным.

2 голосов
/ 21 июня 2011

Вы можете поместить аннотацию @Autowired поверх сервисов, а не использовать их в конструкторе.Это бин, управляемый Spring, что означает, что это синглтон.Это потокобезопасно, но это зависит от реализации.

@Service     
public class DocumentService {  

  @Autowired
  private DocumentGenerationService documentGenerationService;

  @Autowired
  private DocumentPublishService documentPublishService;

... methods follow
1 голос
/ 01 июля 2011

Ваш код выглядит поточно-ориентированным.Spring не гарантирует безопасность потоков, когда он говорит, что бобы одноэлементные.Если вы делаете бин синглтонной области видимости весной, это просто означает, что для каждого контейнера Spring IoC создается один экземпляр объекта.Но, тем не менее, этот класс bean-объекта с одиночной областью действия не может быть потокобезопасным сам по себе, поэтому ответственность его программиста за обеспечение безопасности потока кода *.Это гарантирует, что ссылки не могут измениться, а также из новой модели Java Memory, создание экземпляров гарантировано.Но @duffymo сказал, что объекты, о которых идет речь, также должны быть неизменными.

Остальное все хорошо:)

0 голосов
/ 19 марта 2014

Spring не гарантирует безопасность потоков, когда он говорит, что бобы одноэлементные.Если вы делаете бин синглтонной области видимости весной, это просто означает, что для каждого контейнера Spring IoC создается один экземпляр объекта.Но, тем не менее, этот класс bean-объекта с одной областью действия не может быть потокобезопасным сам по себе, поэтому ответственность его программиста за обеспечение безопасности потока кода

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...