Сделайте `Autowired` внутри метода запуска - PullRequest
0 голосов
/ 25 мая 2020

У меня есть небольшой sp inet of Java code:

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;

import me.cimply.ask.odata.repository.*;

@Component
public class Runner implements CommandLineRunner {

    private static final Logger log = LoggerFactory.getLogger(Runner.class);

    @Autowired
    private IconRepository iconRepository;

    @Autowired
    private UserRepository userRepository;

    @Override
    public void run(String... args) throws Exception {
        this.fillRepository(iconRepository);
        this.fillRepository(userRepository);
    }

    @SuppressWarnings({ "rawtypes", "unchecked" })
    private void fillRepository(BaseRepository repository) {
       // Code
    }
}

Я хочу сделать этот код как можно более общим c.

Я хотел бы извлечь имена всех интерфейсов внутри пакета me.cimply.ask.odata.repository и сгенерировать их экземпляры в al oop в методе run или в конструкторе класса и вызвать fillRepository метод для них.

Другими словами, я хотел бы добавить только новые интерфейсы внутри пакета me.cimply.ask.odata.repository, и приведенный выше код также запускается для них, без добавления новой строки кода каждый раз. Вот. Примерно так псевдокод :

import me.cimply.ask.odata.repository.*;

@Component
public class Runner implements CommandLineRunner {

    private static final Logger log = LoggerFactory.getLogger(Runner.class);

    private BaseRepository repositories[];

    public Runner(){
       for(InterfaceX in me.cimply.ask.odata.repository.*){
          repositories.push(new Autowired instance of InterfaceX);
       }
    }

    @Override
    public void run(String... args) throws Exception {
        for(repo in repositories)
           this.fillRepository(repo);
    }

    @SuppressWarnings({ "rawtypes", "unchecked" })
    private void fillRepository(BaseRepository repository) {
       // Code
    }
}

Обратите внимание, что BaseRepository - это интерфейс в пакете me.cimply.ask.odata.repository, который все остальные интерфейсы реализуют!

Я много искал, и мне кажется, что Autowired должно быть определено как свойство класса, в любом случае, может быть, кто-то знает способ реализации этой идеи!

Ответы [ 2 ]

1 голос
/ 25 мая 2020

Если у вас есть несколько bean-компонентов, реализующих общий интерфейс, определите зависимость в списке интерфейсов, и Spring предоставит вам все доступные реализации:

@Component
public class Runner {
    private final List<Interface> beans;

    @Autowired
    public Runner(final List<Interface> beans) {
        this.beans = beans;
        // beans will contain Bean1, Bean2, Bean3
    }
}

public interface Interface {}

@Component
public class Bean1 implements Interface {}

@Component
public class Bean2 implements Interface {}

@Component
public class Bean3 implements Interface {}
1 голос
/ 25 мая 2020

Если каждый из ваших репозиториев реализует BaseRepository, вы можете это сделать:

import me.cimply.ask.odata.repository.*;

@Component
public class Runner implements CommandLineRunner {

    private List<BaseRepository> repositories;

    @Autowired
    public Runner(List<BaseRepository> repositories){
       this.repositories = repositories;
    }

    @Override
    public void run(String... args) throws Exception {
        for(BaseRepository repo : repositories)
           this.fillRepository(repo);
    }

    @SuppressWarnings({ "rawtypes", "unchecked" })
    private void fillRepository(BaseRepository repository) {
       // Code
    }
}
...