Весна @Репозиторий лучших практик

Контекст: веб-приложение

Я раньше не использовал Spring, но, согласно документам Spring, все бобы являются singleton, если мы не объявим их prototype.

  • Без использования Spring:

Обычно я создаю новый DAO при вызове уровня бизнес-услуги. Если это служба RESTfull, я создаю почти все объекты, зависящие от вызова.

  • С весны:

Я могу аннотировать классы доступа к данным с помощью @Repository а также использовать @Service для классов уровня обслуживания.

Так что мои занятия с выше аннотациями являются singleton по умолчанию. Существует аннотация @Scope которую мы можем объявить как прототип, но никто не делает этого.

  • Без весны: new Object(); каждый раз
  • С весной: singleton

Мои вопросы,

  1. То, как я раньше использовал (создавая новый экземпляр каждый раз), неверно?
  2. Если @Repository является singleton, как он справляется с безопасностью потоков, когда нет такой вещи? (Предположим, что это делается весенними прокси)
  3. Какова наилучшая практика, @Repository достаточно или добавление @Scope('prototype') было бы лучше?
  4. Я не вижу, чтобы кто-то использовал @Scope('prototype') с @Repository (согласно учебникам, блогам и т.д.). Есть ли известная причина?
  5. Что делать, если к моему классу DAO обращаются несколько больших потоков с очень высокой частотой? (Это тот, который я касаюсь больше всего)

благодаря

Ответ 1

Вы правы - в весеннем мире большинство бобов - это одиночные игры.

  1. То, как я раньше использовал (создавая новый экземпляр каждый раз), неверно?

Это неверно, поскольку он работает. Проблема в том, что вы создаете экземпляр DAO для каждого запроса - в некоторых случаях это может быть дорогостоящим, и в любом случае это не имеет никакого смысла - зачем вам понадобиться куча экземпляров DAO? Spring, с другой стороны, не только создает синглтон, но и вводит DAO в сервисы или другие DAO и т.д., Для вас много работы

  1. Если @Repository является одноэлементным, как он справляется с безопасностью потоков, когда нет такой вещи? (Предположим, что это делается весенними прокси)

Когда вы пишете компонент @Repository, вы обычно вводите туда DataSource или EntityManager. Метод DataSource.getConnection() должен быть потокобезопасным. Что касается EntityManager, Spring добавит прокси-сервер, который будет вести себя по-разному для разных потоков, то есть разные потоки не будут использовать один и тот же сеанс JPA.

  1. Какова наилучшая практика, @Repository достаточно или добавление @Scope ('prototype') было бы лучше?

Лучшая практика (или, скорее, самый широкий подход) заключается в том, чтобы просто использовать @Repository

  1. Я не вижу, чтобы кто-то использовал @Scope ('prototype') с @Repository (согласно учебникам, блогам и т.д.). Есть ли известная причина?

Причина в том, что нет никакой выгоды от создания нескольких экземпляров @Repository beans

  1. Что делать, если к моему классу DAO обращаются несколько больших потоков с очень высокой частотой? (Это тот, который я касаюсь больше всего)

Опять же здесь singleton лучше, чем создание нового объекта для каждого запроса. Просто избегайте избыточной синхронизации, чтобы ваши потоки не блокировались на каком-то мониторе

Ответ 2

  1. Нет, но гораздо сложнее провести единичный тест, и это то, что касается инъекции зависимостей. Введя DAO в службу, вы можете легко выполнить тестирование продукта, введя макет DAO во время теста. Это невозможно, если служба создает собственный DAO.

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

  3. Нет никаких оснований для того, чтобы репозиторий был прототипом. Включение прототипа DAO в однопользовательскую службу все равно вызовет одновременный вызов каждого прототипа.

  4. Нет причин для этого.

  5. Нет проблем: он должен быть потокобезопасным, если он правильно закодирован.

Ответ 3

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

Ответ 4

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

Область Singleton (как очевидная) создаст только один экземпляр данного компонента и передаст его всем зависимым объектам.

Область прототипа для каждого зависимого объекта будет создавать свой собственный экземпляр, а не совместно использоваться другими объектами.

Для объектов DAO очень маловероятно, что вам нужно несколько экземпляров для связи с базой данных. Так что синглтон используется в основном всегда.