Подтвердить что ты не робот

Является ли эта конструкция Spring singleton beans потокобезопасной?

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

  • Spring beans сами
  • классы без сохранения
  • неизменяемые классы

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

@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 является неизменным, поскольку невозможно изменить ни одно из его двух полей (которые Spring beans, которые могут быть инициализированы только один раз самим контейнером)?

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

4b9b3361

Ответ 1

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

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

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

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

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

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

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

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

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

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

И если этот проект соблюден, приложение в целом также является потокобезопасным?

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

Ответ 2

Spring не гарантирует безопасность потока. Это ваша ответственность.

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

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

Ответ 3

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

@Service     
public class DocumentService {  

  @Autowired
  private DocumentGenerationService documentGenerationService;

  @Autowired
  private DocumentPublishService documentPublishService;

... methods follow

Ответ 4

Пример кода, показанного в вашем вопросе, определенно потокобезопасен.

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

Ответ 5

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

В вашем коде documentGenerationService, например, является окончательным. Это гарантирует, что ссылки не могут измениться, а также из новой модели Java Memory гарантируется создание экземпляра. Но @duffymo сказал, что объекты, подлежащие передаче, также должны быть неизменными.

Отдых все хорошо:)

Ответ 6

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