@Порядок с разными значениями в двух списках

#java #spring #spring-boot

#java #весна #весенняя загрузка

Вопрос:

Ниже приведено мое требование с простым примером:

 public interface Animal {}

@Component
@Order(1)
public class Hippo implements Animal{}

@Component
@Order(2)
public class Crocodile implements Animal{}
  

Я хочу ввести их в два List с разными порядками. например landAnimals , в первом индексе должен быть бегемот, а во втором индексе — крокодил, в то время как в первом индексе waterAnimals должен быть крокодил, а во втором индексе — бегемот.

 @Autowired
private List<Animal> landAnimals; // 0-Hippo amp; 1-Crocodile (achieved with @Order)

@Autowired
private List<Animal> waterAnimals; // 0-Crocodile amp; 1-Hippo (not achieved)
  

@Order, можем ли мы изменить его динамически?

Ответ №1:

Вы не можете выполнять динамическое использование @Order .

Примечание: я думаю, что вам не нужно создавать два разных списка. Введите один список и при необходимости измените его соответствующим образом.

Вы можете вызвать Collections.reverse() , чтобы изменить список в соответствии с вашими требованиями.

Пример :

 @Autowired
private List<Animal> landAnimals;

public void showOrderList() {
   Collections.reverse(animals);
   for (Animal animal : animals) {
      // do some operation..
   }
}
  

Комментарии:

1. Мне нужно ввести их в разные компоненты, так что это то, что нужно обрабатывать на уровне фреймворка. Решение, о котором я мог подумать, состоит в том, чтобы явно подготовить эти списки с помощью компонента «@» в классе конфигурации «@», а затем внедрить их. Изменение значения порядка «@» на основе условия выглядит невозможным.

Ответ №2:

Поместите порядок в интерфейс:

 public interface Animal {
   int getLandOrder();
   int getWaterOrder();
}
  

Создайте компонент-компонент, который предоставляет списки с разной сортировкой.

 @Service
public class AnimalService {

    private final List<Animals> landAnimals;
    private final List<Animals> waterAnimals;

    // BTW, don't use field injection 
    public AnimalService(List<Animal> animals) {
       // Create copies of the list, because they are sorted in place
       landAnimals = new ArrayList<>(animals);
       landAnimals.sort(Comparator.comparing(Animal::getLandOrder));

       waterAnimals = new ArrayList<>(animals);
       waterAnimals.sort(Comparator.comparing(Animal::getWaterOrder));
    }
    
    public List<Animal> getLandAnimals() {
      return landAnimals;
    }

    public List<Animal> getWaterAnimals() {
      return waterAnimals;
    }
}
  

Теперь введите AnimalService туда, где вам нужен список, и используйте геттеры.

Ответ №3:

Простой способ — использовать PostConstruct , вы можете изменить порядок там, как показано ниже

 @PostConstruct
public void init() {
    waterAnimals.sort(AnnotationAwareOrderComparator.INSTANCE.reversed());
}
  

Комментарии:

1. Обращение вспять может не решить проблему полностью. В будущем у меня может быть больше компонентов, и порядок может быть изменен. В принципе, мне нужно больше гибкости для определения порядка, чтобы в будущем я не был привязан к одному (включая обратный) порядок.

2. @Hamid вы можете написать свой собственный компаратор, обратный только для этой ситуации.

3. Осторожно: sort изменяет список (и в данном случае одноэлементный компонент), поэтому любой другой компонент, который использует список / компонент, будет иметь тот же порядок.

4. @RoToRa вы ошибаетесь, другие компоненты, которые используют этот порядок компонентов / списков, не меняются, вы можете попробовать

5. Вы говорите, что коллекции вводятся как прототипы (отдельный экземпляр для каждого запроса) вместо одноэлементного (один экземпляр для всех запросов), который используется по умолчанию? Можете ли вы показать мне документацию по этому поводу?