How to define a Bean parameter that implements a common functional interface with lambda?

I have a common functional interface:

@FunctionalInterface
public interface Feeder<T extends Animal> {
  void feed(T t);
}

And a couple of beans that implements this interface for different subclasses of Animal.

@Configuration
public class Config {
  @Bean
  public Feeder<Dog> dogFeeder() {
    return dog -> dogService.feedDog(dog);
  }
  @Bean
  public Feeder<Cat> catFeeder() {
    return cat -> catService.feedCat(cat);
  }
}

Now the service class has been added by these beans and it is provided with an instance Animal. How can it determine the correct bean feeder to use?

@Service
public class PetStore {
  @Autowired
  private List<Feeder<? extends Animal> feeders;

  private void feed(Animal animal) {
    //TODO: How to determine the correct feeder from feeders?
    Feeder<? extends Animal> correctFeeder = ....
    correctFeeder.feed(animal);
  }
}

Things I tried:

Originally I thought I would be in the order of using How to get an instance of generics type T but I am faced with the problems that bean is implemented using lambda functions and the type that is returned when you call GenericTypeResolver.resolveTypeArgument(feeder.getClass(), Feeder.class), Animal(!)

beans. GenericTypeResolver Animal, . IntelliJ , , PetStore.

getAnimalClass() . IntelliJ . .

, Animal , , / -, , . . .

, : ?

+6
2

, . , -, getAnimalClass() - ( , ).

canFeed(animal) Feeder ( getAnimalClass()). , Feeder , .

, Feeder, , Class, ( getAnimalClass(), , , ):

final Class<T> typeParameterClass;

public Feeder(Class<T> typeParameterClass){
    typeParameterClass = typeParameterClass;
}

canFeed:

public boolean canFeed(Animal animal) {
   return typeParameterClass.isAssignableFrom(animal.getClass());
}

PetStore :

private Feeder feederFor(Animal animal) {
    return feeders.stream()
                  .filter(feeder -> feeder.canFeed(animal))
                  .findFirst()
                  .orElse((Feeder) unknownAnimal -> {});
}

, . , , , , Spring beans, .

, PetStore Map:

@Autowired
Map<String, Feeder<? extends Animal>> feederMap;

, ( ) . canFeed :

private boolean canFeed(String feederName, Animal animal) {
    return feederName.contains(animal.getClass().getTypeName());
}

Feeder :

private Feeder feederFor(Animal animal) {
    return feederMap.entrySet().stream()
                    .filter(entry -> canFeed(entry.getKey(), animal))
                    .map(Map.Entry::getValue)
                    .findFirst()
                    .orElse((Feeder) unknownAnimal -> {});
}

, , - . , canFeed default Feeder<T>:

default <A extends Animal> boolean canFeed(A animalToFeed) {
    return A == T;
}

, A == T, - A T. , , . Spring, Java:

this.entityBeanType = ((Class) ((ParameterizedType) getClass()
    .getGenericSuperclass()).getActualTypeArguments()[0]);

Feeder Feeder<T>, , . , , ( , invokedynamic), .

, , , . , , , , , , :

, , , , SAM- SAM. , 3% . , / factory, , .

factory, , .

, - . Spring GenericTypeResolver Animal, , -.

, LambdaMetafactory . , Config . ASM , . , , , , Unsafe.defineAnonymousClass. , Class.getConstantPool, ASM , JDK. ( ) , , TypeTools. , , Serialization . , Spring api.

, , (, ), Feeder -hack hack :

default <A extends Animal> boolean canFeed(A animalToFeed) {
    Class<?> feederType = TypeResolver.resolveRawArgument(Feeder.class, this.getClass());
    return feederType.isAssignableFrom(animalToFeed.getClass());
}

PetStore :

@Autowired
private List<Feeder<? extends Animal>> feeders;

public void feed(Animal animal) {
    feederFor(animal).feed(animal);
}

private Feeder feederFor(Animal animal) {
    return feeders.stream()
                  .filter(feeder -> feeder.canFeed(animal))
                  .findFirst()
                  .orElse(unknownAnimal -> {});
}

, , , , , , (, , ) .

+2

"" , . , , . , , . - , . - Java, , , . , , 100% , , .

, . , , , , - , , Animal, , .

, , , Java, , -, , , , AspectJ, - .. , , "" .

, , , , . - Feeding, , , . Animal, , NoFeedingServiceForThatAnimal - . , (enum, , ), , . , , , , , , Feeder.

, , , , , , . .

0

Source: https://habr.com/ru/post/1017206/


All Articles