eliran yosef
eliran yosef

Reputation: 61

Same interface from multiple type

I have an interface, and there are some implementations for this. Each implementation belongs to some type. I want that when I'm using autowired I would able to get all the implementation of the certain type. How can I do it?

public interface someInterface{}

public class impl1OfType1 implements someInterface{}
public class impl2OfType1 implements someInterface{}

public class impl1OfType2 implements someInterface{}
public class impl2OfType2 implements someInterface{}

public class someClass{
   @autowired
   public someClass(List<someInterface> interfaceList){}

}

I want to get only impl1OfType1 and impl2OfType1. And not all the implementation. And at other place I want to get only impl1OfType2 and impl2OfType2.

more concrete example -

    public interface EntityCreator{
      createEntity();
    }

    @Component
    public class DogCreator implements entityCreator{}
    @Component
    public class CatCreator implements entityCreator{}
    @Component
    public class CarCreator implements entityCreator{}
    @Component
    public class TruckCreator implements entityCreator{}

    @Component
    public class AnimalsFactory{
       @Autowired
       public AnimalsFactory(List<EntityCreator> creators){}

    }

Upvotes: 1

Views: 72

Answers (2)

Andrew
Andrew

Reputation: 49656

The solution would be using @Qualifier.

@Component
@Qualifier("place1")
class Impl1OfType2 implements SomeInterface {}

@Component
@Qualifier("place1")
class Impl2OfType2 implements SomeInterface {}

@Service
class SomeClass {
    @Autowired
    public SomeClass(@Qualifier("place1") List<SomeInterface> interfaceList) {
        System.out.println(interfaceList);
    }
}

I slightly changed the names to adhere to the Java convention. They are still a bit awkward and contextless.

UPDATE

You might use generics, Spring is good at dealing with them. For instance, it will inject only DogCreator and CatCreator into a List<EntityCreator<Animal>>.

interface Animal {}
interface Machine {}

interface EntityCreator<T> {}

@Component
class DogCreator implements EntityCreator<Animal> {}
@Component
class CatCreator implements EntityCreator<Animal> {}

@Component
class CarCreator implements EntityCreator<Machine> {}
@Component
class TruckCreator implements EntityCreator<Machine> {}

@Component
class AnimalsFactory {
    @Autowired
    public AnimalsFactory(List<EntityCreator<Animal>> creators) { }
}

UPDATE 2

You could write marker interfaces which would break down existing implementations into logical groups.

interface AnimalCreator {}

interface EntityCreator<T> {}

@Component
class DogCreator implements EntityCreator, AnimalCreator {}
@Component
class CatCreator implements EntityCreator, AnimalCreator {}

@Component
class AnimalsFactory {
    @Autowired
    public AnimalsFactory(List<AnimalCreator> creators) {
        System.out.println(creators);
    }

}

Upvotes: 1

Akshay Mathur
Akshay Mathur

Reputation: 560

If you correct your code with above comments and I understand your problem, I assume this can be a way to solve your issue.

public interface Someinterface<T extends someType> {}
public class someType{}
public class Type1 extends someType{}
public class Type2 extends someType{}

public class TypedInterface1 implements Someinterface<Type1> {}
public class TypedInterface2 implements Someinterface<Type2> {}

public class someClass{
   @Autowired
   public someClass(List<TypedInterface1> interfaceList){}
}

Let me know if I answered your question.

Upvotes: 0

Related Questions