Обычно среда статична, и к тому времени, когда весна начинает запускаться, она уже разрешена.Например, если вы находитесь в среде разработки - приложение запускается со всеми 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-компонентов, поэтому я изложу и это предложение здесь.