внедрить конфигурацию приложения grails в сервис

<p>я создаю службу grails, которая будет взаимодействовать с сторонним api rest через библиотеку java. для библиотеки java требуются учетные данные для api rest с помощью url-адреса, имени пользователя и пароля.</p><p>я хотел бы сохранить эти учетные данные в <code>configuration/config.groovy</code>, сделать их доступными для службы и убедиться, что учетные данные доступны службе, прежде чем они потребуются.</p><p>я ценю, что <code>grailsapplication.config</code> доступен для контроллеров и что с помощью метода службы соответствующие значения конфигурации могут быть предоставлены службе, такой как эта:</p><pre><code>package example class examplecontroller { def exampleservice def index = { } def process = { exampleservice.setcredentials(grailsapplication.config.apicredentials) exampleservice.relevantmethod() } } </code></pre><p><br></p><pre><code>package example import com.example.exampleapiclient; class exampleservice { def credentials def setcredentials(credentials) { this.credentials = credentials } def relevantmethod() { def client = new exampleapiclient( credentials.baseurl, credentials.username, credentials.password ) return client.action(); } } </code></pre><p>я чувствую, что этот подход немного ошибочен, так как зависит от контроллера, вызывающего <code>setcredentials()</code>. наличие учетных данных, автоматически предоставляемых службе, было бы более надежным.</p><p>является ли любой из этих двух вариантов жизнеспособным (я в настоящее время недостаточно знаком с grails):</p><ol> <li> <p>внедрить <code>grailsapplication.config.apicredentials</code> в службу в контроллере при создании службы?</p> </li> <li> <p>предоставить некоторую форму конструктора в службе, которая позволяет передавать учетные данные в службу во время создания экземпляра?</p> </li> </ol><p>внедрение учетных данных в сервис идеально. как это можно сделать?</p>

<p>в сервисах доступен объект <code>grailsapplication</code>, что позволяет:</p><pre><code>package example import com.example.exampleapiclient; class exampleservice { def grailsapplication def relevantmethod() { def client = new exampleapiclient( grailsapplication.config.apicredentials.baseurl grailsapplication.config.apicredentials.username, grailsapplication.config.apicredentials.password ) return client.action(); } } </code></pre>

<p>несмотря на то, что <code>grailsapplication</code> может быть введено в сервисы, я думаю, сервисам не нужно иметь дело с конфигурацией, потому что это сложнее в тестировании и нарушает <a href="http://en.wikipedia.org/wiki/single\_responsibility\_principle">принцип единой ответственности</a> . spring, с другой стороны, может обрабатывать конфигурацию и реализацию более надежным способом. grails имеет <a href="http://grails.org/doc/latest/guide/spring.html">специальный раздел</a> в своих документах.</p><p>чтобы ваш пример работал с использованием spring, вы должны зарегистрировать свой сервис как бин в <code>resources.groovy</code></p><pre><code>// resources.groovy import com.example.exampleapiclient beans { // defines your bean, with constructor params exampleapiclient exampleapiclient, 'baseurl', 'username', 'password' } </code></pre><p>тогда вы сможете внедрить зависимость в ваш сервис</p><pre><code>class exampleservice { def exampleapiclient def relevantmethod(){ exampleapiclient.action() } } </code></pre><p>кроме того, в вашем файле <code>config.groovy</code> вы можете переопределить любое свойство компонента, используя соглашение grails по синтаксису конфигурации: <code>beans.<beanname>.<property></code>:</p><pre><code>// config.groovy ... beans.exampleapiclient.baseurl = 'http://example.org' </code></pre><p>и <code>config.groovy</code>, и <code>resources.groovy</code> поддерживают разные конфигурации среды.</p>

<p>для контекстов, где вы не можете внедрить bean-компонент grailsapplication (служба не относится к числу тех, которые описаны jon cram), например, вспомогательный класс, расположенный в src/groovy, вы можете получить к нему доступ с помощью <strong>holders</strong> = класс:</p><pre><code>def mycontroller { def myaction() { render grailsapplication == grails.util.holders.grailsapplication } } </code></pre>