Несколько реализаций в Spring - PullRequest
0 голосов
/ 14 ноября 2018

У меня есть интерфейс TopicGenerator:

public interface TopicGenerator {
    File create(MultiValueMap params);
    boolean accept(MultiValueMap params);
}

И 3 реализации:

@RequiredArgsConstructor
public class JavaTopicGenerator implements TopicGenerator {
//implementation ommited for readability

@RequiredArgsConstructor
public class PhpTopicGenerator implements TopicGenerator {
//implementation ommited for readability

@RequiredArgsConstructor
public class CppTopicGenerator implements TopicGenerator {
//implementation ommited for readability

Теперь я пытаюсь использовать их в зависимости от моих параметров, поэтому я создал специальныйTopicFacade.

@RequiredArgsConstructor
public class TopicFacade {

    @NonNull
    private final TopicService topicService;

    @NonNull
    private final List<TopicGenerator> topicGenerators;

    public void generate(MultiValueMap<String, String> params, HttpServletResponse response) {
        for (TopicGenerator topicGenerator : topicGenerators) {
            if (topicGenerator.accept(params)) {
                File tempFile = topicService.generate(params);
                //do something else.
            }
        }
    }
}

Где на моем TopicServiceImpl у меня есть:

@Service
@RequiredArgsConstructor
public class TopicServiceImpl implements TopicService {

    @NonNull
    private final List<TopicGenerator> reportGenerators;

        public File generate(MultiValueMap params) {
        for (TopicGenerator topicGenerator : topicGenerators) {
            if (topicGenerator.create(params)) {
                return topicGenerator.export(params);
            }
        }

Я получаю сообщение об ошибке типа: Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'topicServiceImpl': Unsatisfied dependency expressed through field 'topicGenerators'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'java.util.List<com.topic.service.TopicGenerator>' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}

(Ранее, когда я использовалВнедрение в поле вместо конструктора Я смог добавить @Service до того, как одна из трех реализаций и код работали над этой единственной реализацией, но это не то, что я ищу)

Ответы [ 2 ]

0 голосов
/ 14 ноября 2018

Может определять бин типа List<TopicGenerator>, как показано ниже:

@Configuration
public class AppConfig {

    @Autowired
    private TopicGenerator cppTopicGenerator;

    @Autowired
    private TopicGenerator phpTopicGenerator;

    @Autowired
    private TopicGenerator javaTopicGenerator;

    @Bean
    public List<TopicGenerator> topicGeneratorList()
    {
        return Arrays.asList(cppTopicGenerator, phpTopicGenerator, javaTopicGenerator);
    }
}

При этом ваш оригинальный код должен нормально работать.

Бобы могут быть переданы в camelCase их соответствующего имени класса. Например, cppTopicGenerator будет ссылаться на компонент класса CppTopicGenerator.java. Хотя лучше использовать @Qualifier для большей ясности.

0 голосов
/ 14 ноября 2018

Использовать квалификатор аннотация. https://www.tutorialspoint.com/spring/spring_qualifier_annotation.htm

https://stackoverflow.com/a/40844528/4587961

Тогда ваш Фасад может иметь все эти реализации. И у вас есть метод, который будет возвращать конкретную реализацию в зависимости от вашего состояния.

Затем инициализируйте свой список после автоматической передачи всех зависимостей. https://stackoverflow.com/a/8519295/4587961

@Service // Try and play around with annotations.
public class TopicFacade {

    @Autowired
    @Qualifier("Service1")
    private final TopicService topicService1;

    //... The same stuff for other services.

    @Autowired
    @Qualifier("ServiceN")
    private final TopicService topicServiceN;

    //Initialize this in the post construct and put all your services there.
    @NonNull
    private final List<TopicGenerator> topicGenerators = new ArrayList();

    @PostConstruct
    public void initTopicGenerators() throws Exception {
        topicGenerators.add(topicService1);
        //And others.
        topicGenerators.add(topicServiceN);
    }

    public void generate(MultiValueMap<String, String> params, HttpServletResponse response) {
        for (ReportGenerator reportGenerator : reportGenerators) {
            if (reportGenerator.accept(params)) {
                File tempFile = topicService.generate(params);
                //do something else.
            }
        }
    }
}
...