@Order with different values in two Lists

Viewed 187

Below is my requirement with a simple example:

public interface Animal {}

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

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

I want to inject them into two List's with different orders. eg landAnimals should have Hippo in the first index and Crocodile in the second index while waterAnimals should have Crocodile in the first index and Hippo in the second index.

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

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

@Order, can we change it dynamically?

3 Answers

There is no way you can do dynamically using @Order.

Note: I think that you don't need to create two different lists. Inject a single list and reverse accordingly when required.

You can call Collections.reverse() to reverse the list for your requirement.

Example :

@Autowired
private List<Animal> landAnimals;

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

Simple way is use PostConstruct, you can change the order in there like below

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

Put the order into the interface:

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

Create a service bean that provides the differently sorted lists.

@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;
    }
}

Now inject AnimalService where you need a list, and use the getters.

Related