Einige Feinheiten der Injektionskollektionen im Frühjahr

Hallo alle zusammen! Ich heiße Vladislav Rodin. Ich unterrichte derzeit Kurse über Softwarearchitektur und Hochlast-Softwarearchitektur auf dem OTUS-Portal. Jetzt gibt es in OTUS ein offenes Set für den neuen Thread des Entwicklerkurses zum Spring Framework . Im Vorfeld des Kursbeginns habe ich beschlossen, ein kleines Copyright-Material zu schreiben, das ich mit Ihnen teilen möchte.





Hintergrund


Der Frühling enthält viel „Magie“ in sich selbst und führt einige nicht offensichtliche Dinge selbst aus. Unwissenheit oder Missverständnisse können zu Nebenwirkungen führen, die beim Schreiben Ihrer Bewerbung mit diesem Framework auftreten können.

Eines dieser nicht offensichtlichen Dinge ist das Einfügen von Java Collection Framework-Schnittstellen. Nachdem ich selbständig auf einen Rechen zu diesem Thema getreten war und die nächsten Fragen von meinen Kollegen gehört hatte, beschloss ich, ihn zu sortieren und die Ergebnisse meiner Forschung in Form eines Artikels aufzuzeichnen, in der Hoffnung, dass er jemandem helfen würde, der bereits in Arbeit ist oder während der ersten Entwicklung des Frühlings.

Szenario


Schauen wir uns einen Dienst an, der mit Filmhelden funktioniert. Es werden 3 von ihnen sein: Rambo, Terminator und Gandalf. Jeder von ihnen wird eine eigene Klasse repräsentieren und ihre Eltern werden gemeinsam sein - Hero.

public class Hero {
}

@Component
public class Rambo extends Hero {

    @Override
    public String toString() {
        return "Rambo";
    }
}

@Component
public class Terminator extends Hero {

    @Override
    public String toString() {
        return "Terminator";
    }
}


@Component
public class Gandalf extends Hero {
    @Override
    public String toString() {
        return "Gandalf";
    }
}

Injektionsliste


Nehmen wir an, wir wollen einen Dienst schaffen, der mit den Helden der Militanten zusammenarbeitet. Wahrscheinlich müssen Sie eine Liste solcher Helden hinzufügen.

Kein Problem! Erstellen Sie einen Dienst und eine Konfiguration:

@Service
@Getter
public class ActionHeroesService {
    @Autowired
    List<Hero> actionHeroes;
}

@Configuration
public class HeroesConfig {

    @Bean
    public List<Hero> action() {
        List<Hero> result = new ArrayList<>();
        result.add(new Terminator());
        result.add(new Rambo());
        return result;
    }
}

Alles ist in Ordnung, aber bei der Überprüfung kann festgestellt werden, dass Gandalf auf der Liste steht!

Als Spring sah, dass es notwendig ist, die Liste zu injizieren, umging er die im Kontext befindlichen Beans, fand unter ihnen alle, die zum generischen Typ passen, sammelte die Liste von ihnen und injizierte sie, wobei er unsere Liste ignorierte.

Wie bringt man den Frühling dazu, das zu tun, was wir wollen?

Option 1. Krücke


Da das Problem genau darin besteht, die Schnittstelle des Java Collection Framework einzufügen, können Sie List im Dienst und natürlich in der Konfiguration einfach durch ArrayList ersetzen, damit Spring eine Instanz der von uns benötigten Klasse findet. Dann wird alles wie erwartet funktionieren.

@Configuration
public class HeroesConfig {

    @Bean
    public ArrayList<Hero> action() {
        ArrayList<Hero> result = new ArrayList<>();
        result.add(new Terminator());
        result.add(new Rambo());
        return result;
    }
}

@Service
@Getter
public class ActionHeroesService {
    @Autowired
    ArrayList<Hero> actionHeroes;
}

Option 2. Richtiger


Eine andere Möglichkeit, Spring die Hände zu binden, besteht darin, ihn zu bitten, nicht nur eine Liste, sondern eine Bohne mit einem speziellen Namen in den Dienst aufzunehmen und Qualifier hinzuzufügen. So können wir unsere Bohne injizieren.

@Service
@Getter
public class ActionHeroesService {
    @Autowired
    @Qualifier("action")
    List<Hero> actionHeroes;
}

Injektionskarten


Wenn viele Leute über die Nuance der Injektion von List Bescheid wissen, ist es mit der Karte im Allgemeinen schlimmer.
Schreiben wir einen Dienst, der mit den Hauptfiguren der Filme zusammenarbeitet. Es wird eine Karte eingefügt, die die Namen der Filme anhand der Tasten und der Werte der Bohnen der Hauptfiguren enthält:

@Service
@Getter
public class MainCharactersService {
    @Autowired
    Map<String, Hero> mainCharactersByFilmName;
}

@Configuration
public class HeroesConfig {

    @Bean
    public Map<String, Hero> mainCharactersByFilmName() {
        Map<String, Hero> result = new HashMap<>();

        result.put("rambo", new Rambo());
        result.put("terminator", new Terminator());
        result.put("LOTR", new Gandalf());

        return result;
    }
}

Beim Start können Sie sehen, dass Gandalfs Schlüssel nicht LOTR ist, sondern Gandalf, woraus wir schließen können, dass nicht der Name des Films geschrieben wurde, sondern der Name der Bohne, während es im Fall von Rimbaud und dem Terminator nur Glück war: Die Namen der Hauptfiguren stimmen überein Filmtitel.

Wenn eine Map eingefügt werden muss, deren Schlüssel String ist, und der Wert der Beans, ignoriert Spring (wie im Fall der Liste) einfach die von uns vorgeschlagene Map, geht den Kontext durch und sammelt alle geeigneten Beans s und erstellt eine Karte mit ihnen als Werten und mit ihren Namen als Schlüssel.

Die Problemumgehungen ähneln denen, die für die Liste verwendet wurden:

Option 1. Krücke


Karte durch HashMap ersetzen:

@Service
@Getter
public class MainCharactersService {
    @Autowired
    HashMap<String, Hero> mainCharactersByFilmName;
}


@Configuration
public class HeroesConfig {

    @Bean
    public HashMap<String, Hero> mainCharactersByFilmName() {
        HashMap<String, Hero> result = new HashMap<>();

        result.put("rambo", new Rambo());
        result.put("terminator", new Terminator());
        result.put("LOTR", new Gandalf());

        return result;
    }
}

Option 2. Richtiger


Qualifikation hinzufügen:

@Service
@Getter
public class MainCharactersService {
    @Autowired
    @Qualifier("mainCharactersByFilmName")
    Map<String, Hero> mainCharactersByFilmName;
}

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


All Articles