2017-02-15 16 views
0

У меня есть (весенняя) служба, отправляющая электронные письма через различные клиентские адаптеры, в зависимости от среды, в которой они работают. Поэтому, когда я нахожусь на dev, я хочу использовать ClientAdapterA и в прямом эфире ClientAdapterB. Использование выглядит следующим образом:Способ настройки адаптера для autowire через yml

@Service 
public class EmailService { 

    @Autowired 
    private ClientAdapter clientAdapter; 

    public EmailResponse send(EmailRequest emailRequest) { 
     return clientAdapter.sendMail(emailRequest); 
    } 
} 

конфигурации я хочу, чтобы произойти через мой application.yml:

mail: 
    adapter: ClientAdapterA 

Я попытался использовать @Qualifier но, что позволяет только использование одного жесткого кодировкой адаптера:

@Qualifier("ClientAdapterB") 
@AutoWired 
private ClientAdapter clientAdapter; 

Я также попытался создать класс Config, который должен обеспечить соответствующий компонент, но это не сработало:

@Configuration 
public class JavaBeansAdapterConfig { 

    @Value("${mail.adapter}") 
    private String adapterName; 

    @Bean 
    public ClientAdapter clientAdapterImplementation() throws ClassNotFoundException { 
     ApplicationContext ctx = new AnnotationConfigApplicationContext(); 
     return (ClientAdapter)ctx.getAutowireCapableBeanFactory().createBean(Class.forName(adapterName)); 
    } 
} 

Что я делаю неправильно, или есть даже способ сделать это, как я хочу? Любая помощь приветствуется, спасибо.

+0

Используйте '@ Profile' и загружайте один боб или другой в зависимости от профиля ... –

ответ

0

Я пробовал с именем пакета, но это только фиксированная половина проблем. Я по-прежнему не мог использовать автозависимость от зависимостей, поэтому я сделал еще несколько копаний и наткнулся на this solution.

Моя конфигурация адаптера теперь выглядит следующим образом:

@Component 
@Setter 
@Getter 
@ConfigurationProperties(prefix = "mail.adapter") 
public class ClientAdapterConfig { 

    @Qualifier("mailClientA") 
    @Autowired 
    private ClientAdapter mailClientA; 

    @Qualifier("mailClientB") 
    @Autowired 
    private ClientAdapter mailClientB; 

    private String name; 

    @Bean 
    @Primary 
    public ClientAdapter getAdapter() 
    { 
     ClientAdapter adapter = null; 
     switch (name) { 
      case "mailClientA": 
       adapter = mailClientA; 
       break; 
      case "mailClientB": 
       adapter = mailClientB; 
       break; 
      default: 
       break; 
     } 

     return adapter; 
    } 
} 

С @Qualifier аннотацию я убеждаюсь, что он ставит в адаптере я хочу.

Создание Bean @Primary затем обеспечивает его правильно autowired в EmailService (который остается неизменным по сравнению с блоком в вопросе)

Я знаю, что это на самом деле не конфигурации в смысле Spring, но в этот момент это достаточно хорошо для меня.

0

Определите свой компонент, используя Class.forName(). Но вам также нужно установить packageName. См. Ниже:

@Configuration 
public class JavaBeansAdapterConfig { 

    @Value("${mail.adapter}") 
    private String adapterName; 

    private final String packageName = "com.foo.bar"; 

    @Bean 
    public ClientAdapter clientAdapterImplementation() throws ClassNotFoundException, IllegalAccessException, InstantiationException { 
     return (ClientAdapter) Class.forName(packageName + "." + adapterName).newInstance(); 
    } 
} 

 Смежные вопросы

  • Нет связанных вопросов^_^