До сих пор у меня было очень простое определение bean-компонента, которое выглядело так:

@Bean
@Conditional(value=ConditionClass.class)
SomeInterface myMethodImpl(){
    return new ImplementationOne();
}

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

Так что мне нужно что-то вроде этого:

@Bean
@Conditional(value=ConditionClass.class)
SomeInterface myMethodImpl(){
    return context.getEnvironment().getProperty("optionEnabled") ? new 
   ImplementationOne() : new ImplementationTwo();
}

По сути, способ создания экземпляра правильной реализации во время определения компонента на основе значения конфигурации. Возможно ли это, и может ли кто-нибудь привести пример? Спасибо

3
Zed 23 Окт 2018 в 15:57

2 ответа

Лучший ответ

Это можно реализовать без использования @Conditional.

Предполагая, что у вас есть интерфейс SomeInterface и две реализации ImplOne ImplTwo:

SomeInterface.java

public interface SomeInterface {
    void someMethod();
}

ImplOne.java

public class ImplOne implements SomeInterface{
    @Override
    public void someMethod() {
       // do something
    }
}

ImplTwo.java

public class ImplTwo implements SomeInterface{
    @Override
    public void someMethod() {
       // do something else
    }
}

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

MyConfig.java

@Configuration
public class MyConfig {

    @Autowired
    private ApplicationContext context;

    @Bean
    public SomeInterface someInterface() {
        if (this.context.getEnvironment().getProperty("implementation") != null) {
            return new ImplementationOne();
        } else {
            return new ImplementationTwo();
        }
    }
}

Убедитесь, что сканирование компонентов пружины обнаруживает MyConfig. Затем вы можете использовать @Autowired, чтобы внедрить правильную реализацию в любое другое место вашего кода.

2
sirain 23 Окт 2018 в 13:43

Я думаю, вы делаете это неправильно.

Вы должны использовать @Conditional() в своей реализации, а не в интерфейсе.

Вот как я бы это сделал:

Интерфейс, который вы будете использовать в своем коде.

MyInterface.java

public interface MyInterface {
   void myMethod();
}

Первая реализация:

MyInterfaceImplOne.java

@Bean
@Conditional(MyInterfaceImplOneCondition.class)
public class MyInterfaceImplOne implements MyInterface {
   void myMethod(){
     // dosmthg
    }
}

MyInterfaceImplOneCondition.java

public class MyInterfaceImplOneCondition implements Condition {
    @Override
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
       return context.getEnvironment().getProperty("optionEnabled")
    }
}

И для второй реализации:

MyInterfaceImplTwo.java

@Bean
@Conditional(MyInterfaceImplTwoCondition.class)
public class MyInterfaceImplTwo implements MyInterface {
   void myMethod(){
     // dosmthg 2
    }
}

MyInterfaceImplTwoCondition.java

public class MyInterfaceImplTwoCondition implements Condition {
    @Override
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
       return !context.getEnvironment().getProperty("optionEnabled")
    }
}

В этом случае вам просто нужно вызвать интерфейс, и Spring внедрит компонент, соответствующий правильному условию.

Надеюсь, это то, что вы ищете, и я был достаточно ясен!

1
sirain 23 Окт 2018 в 13:19
52949694