Можно ли решить, какой компонент использовать в зависимости от переменных пути с помощью @Autowire? - PullRequest
1 голос
/ 17 мая 2019

В эти дни я играю с Spring и застрял, пытаясь автоматически связывать бины при жизни HTTP-запроса.

У меня есть интерфейс с именем Animal и две реализации, Dog и Cat:

Animal.java

public interface Animal {
  public String sound();
}

Dog.java

public class Dog implements Animal {
  @Override
  public String sound() {return "Woof!";}
}

Cat.java

public class Cat implements Animal {
  @Override
  public String sound() {return "Meow... :3";}
}

Мой контроллер выглядит так:

AnimalController.jav a

@RestController
@RequestMapping(value="/animal")
public class AnimalController {
  private final AnimalService animalService;

  @Autowired
  public AnimalController(AnimalService service) {
    animalService = service;
  }

  @GetMapping(value = "/{animal}/sound")
  public String animalSound(@PathVariable String animal) {
    return animalService.doSound();
  }
}

AnimalService.java (Здесь я не могу автоматически подключить своих животных):

@Service
public class AnimalService {

/* 
 My IDE prompts:  
 'Could not autowire. There is more than one bean of `Animal` type.'
*/
  @Autowired
  private Animal animal; 

  public String doSound() {
    return animal.sound();
  }
}    
}

Также:

Configuration.java

@Configuration
public class Configuration {
  @Bean
  public Dog createDog() {
    return new Dog();
  }

  @Bean
  public Cat createCat() {
    return new Cat();
  }
}

Возможно ли иметь такое поведение, решая, какой компонент использовать в зависимости от переменных пути?Я пытался прочитать основную документацию Spring, но я не мог понять слишком много.Буду признателен за помощь.

Ответы [ 3 ]

2 голосов
/ 17 мая 2019

Вы можете создать экземпляр всех бинов типа Animal, сделав их списком.Пример:

@Autowired
List<Animal> animals;

Это автоматически соединит всех животных, и вы сможете перебирать их и программно решать, какое вам нужно.

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

1 голос
/ 17 мая 2019

получить боб животного из контейнера по имени beanName;

@RestController
@RequestMapping(value="/animal")
public class AnimalController {

private final AnimalService animalService;

  @Autowired
  public AnimalController(AnimalService service) {
    animalService = service;
  }


  @GetMapping(value = "/{animal}/sound")
  public String animalSound(@PathVariable String animal) {
    return animalService.doSound(animal);
  }

} 

AnimalService.java

public class AnimalService implements ApplicationContextAware {

private ApplicationContext applicationContext;

@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
    this.applicationContext = applicationContext;
}


public String doSound(String animalName) {
    Animal animal = applicationContext.getBean(animalName);
return animal.sound();
 }

}
1 голос
/ 17 мая 2019

Вы можете использовать spring.profiles.active, чтобы сделать это.Один профиль загружает собаку, а другой - кошку.

  @Configuration
public class Configuration {

@Profile("dog")
  @Bean
  public Dog createDog() {
    return new Dog();
  }

@Profile("cat")
  @Bean
  public Cat createCat() {
    return new Cat();
  }
}

И вы можете запустить свое приложение как java -jar myapp.jar --spring.profiles.active = dog.

Другойвариант, который вы можете попробовать, это квалифицировать bean-компоненты и использовать Qualifier с переменной свойства, Spring может разрешить его.

@Service
public class AnimalService {

  @Qualifier("${choosen.animal}")
  @Autowired
  private Animal animal; 

  public String doSound() {
    return animal.sound();
  }
}    
}

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