Конфигурация сервиса Grails для конкретной среды

Каков наилучший способ настроить службу Grails со значениями, специфичными для среды? Я считаю, что есть два варианта:

  1. получить доступ к значениям grailsApplication из класса обслуживания или
  2. сконфигурируйте служебный компонент в закрытии компонентов в Config.groovy или resources.groovy.

Я видел пару постов о stackru и других местах, которые показывают, как сделать #1 (доступ к приложению grailsApplication в сервисе). Один из таких постов: Внедрить конфигурацию приложения Grails в сервис.

Однако я думаю, что это создает ненужную связь сервиса с Grails. Разве это не похоже на доступ к приложению SpringContext в pojo, а не на настройку / ввод значений? Кроме того, мне пока не повезло заставить его работать в модульном тесте класса обслуживания.

В двух книгах есть примеры введения свойств (подход № 2). В книге "Полное руководство к Grails 2", глава 10, раздел "Услуги в действии" показано, как это сделать, но без особой ценности для среды. В книге Groovy и Grails Recipes, раздел 16-2, также показан пример использования resources.groovy, но я пока не смог заставить его работать.

Следующий пост в блоге также имеет хороший пример, но не зависит от конкретной среды: http://ldaley.com/post/1253952347/getting-more-out-of-property-override-configuration. Глава 15 Справочника Grails также согласуется с этими примерами и показывает, как установить свойства для bean-компонента для каждой среды.

Тем не менее, ни один из примеров того или иного подхода не дает какого-либо мнения или рационального подхода к тому или иному подходу. Неужели нет никаких плюсов и минусов в любом подходе? Разве инъекционный подход не был бы проще для модульного тестирования и более соответствовал бы весеннему образу жизни?

Натан

2 ответа

Решение

Я бы сказал, используйте тот, который вам удобнее. Я склонен идти с доступом grailsApplication.config непосредственно из сервиса, потому что это позволяет вам сделать конфигурацию более "семантической" (если не сказать лучшего слова) в том смысле, что вы можете называть параметры конфигурации в соответствии с тем, что они делают, а не с тем бином, которым они управляют. И если два (или более) разных бина должны знать адрес электронной почты администратора сайта (например), то они оба могут прочитать grailsApplication.config.myapp.admin.email а не моя необходимость настраивать beans.monitorService.destinationEmail а также beans.userService.fromEmail по отдельности.

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

Существует различие в концепции служб (классы, которые существуют в папке служб) и Spring Beans, определенных в resources.groovy,

Для сервисов Grails уже настроены транзакции:

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

Spring Beans, которые вы объявили, не являются транзакционными по умолчанию.

"Однако я думаю, что это создает ненужную связь сервиса с Grails"

Так как сервисы Grails отличаются от Spring Beans, я не вижу проблем при использовании подхода № 1.

Для модульных тестов вам нужно вручную подключить ваш сервисный экземпляр. Пример:

class MyService {
  def grailsApplication
}

class MyServiceTests {
  MyService getServiceInstance() {
    MyService myService = new MyService()
    myService.grailsApplication = grailsApplication //static attribute in unit tests
    return myService
  }
}
Другие вопросы по тегам