запрос зависимой инъекции бобов - PullRequest
0 голосов
/ 04 июня 2019

Сценарий. Конфигурация в моем приложении для весенней загрузки зависит от среды, скажем, Разработка, Тестирование и Производство. Эти конфигурации обычно загружаются в зависимости от среды развертывания.

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

Решения, которые я пробовал:

  1. Моим первоначальным вариантом было обновить активные профили, когда я получаю запрос к контроллеру, но для этого требуется перезагрузка конфигураций.

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

Ответы [ 2 ]

0 голосов
/ 04 июня 2019

Обычно среда статична, и к тому времени, когда весна начинает запускаться, она уже разрешена.Например, если вы находитесь в среде разработки - приложение запускается со всеми bean-компонентами / конфигурациями, определенными для этой среды.

Я также не понимаю, насколько логически возможно, что один и тот же процесс java обслуживает / развертывает во всех средах.одновременно, может быть, вы должны привести конкретные примеры кода, который у вас есть, по крайней мере, на уровне интерфейсов.

Spring спроектирован таким образом (по крайней мере, его обычное использование), что после создания bean-компонентов (контекст приложения являетсяначало) они обслуживают все запросы, и вы никогда не перезагрузите их, если они находятся в Scope Singleton.

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

Так что, в сущности, вы хотите против дизайна пружины, если хотите.

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

Вот пример решения:

  enum Environment {
     DEV,
     TEST,
     PROD  
  }

  interface SomeStrategyOfEnvironmentDependentCode {
      void invoke();
  }

  @Service
  public class MyRefactoredService {

      private Map<Environment, SomeStrategyOfEnvironmentDependentCode> envStrategies;


      public void foo(Environment env) {
              envStrategies.get().invoke();
      }
  }

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

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

Опять же, лучший способ - думать о среде как о чем-то статичном, существующем и определяющем при запуске, какая реализация актуальна.

Пример, скажем, в dev вы используете postgres, в рабочей среде oracle (только дляради примера).

Итак, вы можете определить что-то вроде этого:

appliction-dev.properties 

db.oracle.enabled=false
db.postgres.enabled=true
db.postgres.user=...
db.postgres.password=...
--------------------------


application-prod.properties

db.oracle.enabled=true
db.postgres.enabled=false
db.oracle.user=...
db.oracle.password=...

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

@Configuration
@ConditionalOnProperty(name="db.oracle.enabled", havingValue = true)
public class OracleBaseConfiguration  {
      @Bean
      public DataSource dataSource () {
            //create oracle Datasource out of oracle configurations 
      }
}


@Configuration
@ConditionalOnProperty(name="db.postgres.enabled", havingValue = true)
public class PostgresBaseConfiguration  {
      @Bean
      public DataSource dataSource () {
            //create postgres Datasource out of oracle configurations 
      }
}

Если у вас абсолютно нет выбора, то в Spring есть две техники, которые могут быть полезны:

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

Техника 1: в случае, когда среды известны заранее:

Все бины могут реализовывать один и тот же интерфейс:

 interface EnvironmentAware {
    void doSomething();
    Environment getEnvironment();
 }


 class BeanForDev implements EnvironmentAware {
     public Environment getEnvironment() {
        return Environment.DEV;
     }
     public void doSomething() {...}
  }


  class BeanForProd implements EnvironmentAware {
     public Environment getEnvironment() {
        return Environment.PROD;
     }
     public void doSomething() {...}
  }

  public class MyService {
      private Map<Environment, EnvironmentAware> beans;

      public MyService(List<EnvironmentAware> beans) {
          // here is a trick - when you inject a list, spring will find all beans implementing the interface and inject them. So this is your autowired construction
        // so make it map and pick the bean from the map in runtime
      }

Техника 2

Когда среды теперь известны заранее, но определены в конфигурациях.Снова следуем предложению создать бин для среды

. Весной возможно динамическое создание Бинов (скажем, для среды) с помощью BeanFactoryPostProcessor.Вы можете реализовать этот интерфейс и зарегистрировать динамически созданные определения бинов.Это довольно продвинутый материал, так что вы должны в значительной степени понять, как работает spring, чтобы использовать эту концепцию, но технически это может помочь в динамическом создании bean-компонентов, поэтому я изложу и это предложение здесь.

0 голосов
/ 04 июня 2019

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

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