Как сделать условную автопроводку весной?


кто-нибудь пытался автоматически подключать разные бобы к управляемому пружиной Бобу на основе условия? Например, если выполняется какое-то условие, введите класс A, иначе B? Я видел в одном из результатов поиска Google, что это возможно с помощью SpEL (Spring Expression Language), но не смог найти рабочий пример.

1   51   2013-10-07 16:36:22

1 ответ:

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

Factory bean

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

public MyBeanFactoryBean implements FactoryBean<MyBean> {

    // Using app context instead of bean references so that the unused 
    // dependency can be left uninitialized if it is lazily initialized
    @Autowired
    private ApplicationContext applicationContext;

    public MyBean getObject() {
        MyBean myBean = new MyBean();
        if (true /* some condition */) {
            myBean.setDependency(applicationContext.getBean(DependencyX.class));
        } else {
            myBean.setDependency(applicationContext.getBean(DependencyY.class));
        }
        return myBean;
    }

    // Implementation of isSingleton => false and getObjectType

}

может быть, немного лучше, если вы используете factory bean создать зависимость фасоли в случае, если вы хотите иметь только один такой фасоли в контекст приложения:

public MyDependencyFactoryBean implements FactoryBean<MyDependency> {

    public MyDependency getObject() {
        if (true /* some condition */) {
            return new MyDependencyX();
        } else {
            return new MyDependencyY();
        }
    }

    // Implementation of isSingleton => false and getObjectType

}

SpEL

С SpEL есть много возможностей. Наиболее распространенными являются системное свойство условия:

<bean class="com.example.MyBean">
    <property name="dependency" value="#{systemProperties['foo'] == 'bar' ? dependencyX : dependencyY}" />
</bean>

свойства заполнителя

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

<bean class="com.example.MyBean">
    <property name="dependency" ref="${dependencyName}" />
</bean>

Весна профили

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

<!-- Default dependency which is referred by myBean -->
<bean id="dependency" class="com.example.DependencyX" />

<beans profile="myProfile">
    <!-- Override `dependency` definition if myProfile is active -->
    <bean id="dependency" class="com.example.DependencyY" />
</beans>

другие методы могут пометить определение bean как lazy-init="true", но определение будет по-прежнему зарегистрировано в контексте приложения (и делает вашу жизнь сложнее при использовании неквалифицированного autowiring). Вы также можете использовать профили с @Component на основе бобов через @Profile Примечание.

Регистрация ApplicationContextInitialier (или пример), чтобы увидеть, как вы может активировать профили программно (т. е. на основе ваше условие).

Java config

вот почему Java на основе конфигурации является настолько популярным, как вы можете сделать:

@Bean
public MyBean myBean() {
    MyBean myBean = new MyBean();
    if (true /* some condition */) {
        myBean.setDependency(dependencyX());
    } else {
        myBean.setDependency(dependencyY());
    }
    return myBean;
}

конечно, вы можете использовать более или менее все методы конфигурации в конфигурации на основе java, а также (через @Profile,@Value или @Qualifier + @Autowired).

постпроцессор

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

BeanFactoryPostProcessors может читать и изменять определения bean (например, свойство placeholder ${} разрешение реализуется таким образом).

BeanPostProcessors может обрабатывать экземпляры bean. Можно проверить свежесозданный Боб и поиграть с ним (например @Scheduled обработка аннотаций осуществляется таким образом).

MergedBeanDefinitionPostProcessor расширение постпроцессор в зернах и может изменить определение bean непосредственно перед его созданием (@Autowired обработка аннотаций осуществляется таким образом).


обновление октября 2015

  • Весна 4 добавила новый метод, как это сделать условная Регистрация бобов через @Conditional Примечание. Это тоже стоит проверить.

  • конечно есть множество других способов с Spring Boot только через его @ConditionalOn*.

  • также обратите внимание, что оба @Import и @ComponentScan (и их XML-аналоги) проходят разрешение свойств (т. е. вы можете использовать ${}).