بعض التفاصيل الدقيقة لمجموعات الحقن في الربيع

تحية للجميع! اسمي فلاديسلاف رودين. أقوم حاليًا بتدريس دورات حول هندسة البرمجيات وهندسة البرمجيات ذات الحمولة العالية على بوابة OTUS. الآن في OTUS هناك مجموعة مفتوحة لمؤشر الترابط الجديد لدورة المطور في إطار عمل الربيع . تحسبًا لبدء الدورة ، قررت كتابة بعض مواد حقوق الطبع والنشر التي أريد مشاركتها معك.





خلفية


يحتوي الربيع على الكثير من "السحر" في حد ذاته ، ويقوم ببعض الأشياء غير الواضحة من تلقاء نفسه. يمكن أن يؤدي الجهل أو سوء الفهم لهذا إلى آثار جانبية قد تواجهها في عملية كتابة طلبك باستخدام هذا الإطار.

أحد هذه الأشياء غير الواضحة هو حقن واجهات Java Collection Framework. بعد أن خطوت بشكل مستقل على أشعل النار يتعلق بهذا الموضوع ، وبعد سماع الأسئلة التالية من زملائي ، قررت فرزها وتسجيل نتائج بحثي في ​​شكل مقال على أمل أن يساعد شخصًا بالفعل في العمل أو أثناء التطوير الأولي لـ Spring.

سيناريو


دعونا نلقي نظرة على خدمة ستعمل مع أبطال الأفلام. سيكون هناك 3 منهم: Rambo و Terminator و Gandalf. كل منهم سيمثل فئة منفصلة ، وسيكون والدهم مشتركًا - بطل.

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

قائمة الحقن


لنفترض أننا نريد إنشاء خدمة ستعمل مع أبطال المسلحين. ربما ، سيكون عليك حقن قائمة بأبطال مثل هؤلاء في ذلك.

ليس هناك أى مشكلة! إنشاء خدمة وتكوين:

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

كل شيء على ما يرام ، ولكن عند التحقق من ذلك ، يمكن العثور على Gandalf في القائمة!

الربيع ، بالنظر إلى أنه كان من الضروري حقن القائمة ، وتجاوز الفاصوليا الموجودة في السياق ، ووجد بينها كل ما يناسب النوع العام ، وجمع القائمة منها وحقنها ، متجاهلاً قائمتنا.

كيف نجعل Spring يفعل ما نريد؟

الخيار 1. عكاز


نظرًا لأن المشكلة تكمن في محاولة إدخال واجهة Java Collection Framework ، يمكنك ببساطة استبدال List بـ ArrayList في الخدمة ، وبالطبع في التهيئة بحيث يعثر Spring على مثيل من الفصل الدراسي الذي نحتاج إليه. ثم سيعمل كل شيء كما توقعنا.

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

الخيار 2. الأصح


طريقة أخرى لربط أيدي سبرينغ هي أن تطلب منه أن يدخل في الخدمة ليس فقط أي قائمة ، بل حبة تحمل اسمًا خاصًا ، مضيفًا مؤهلاً. وبالتالي ، سوف نكون قادرين على حقن الفول.

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

خرائط الحقن


إذا كان الكثير من الناس يعرفون الفروق الدقيقة لحقن القائمة ، فإن الأمور تكون عمومًا أسوأ مع الخريطة.
دعونا نكتب خدمة ستعمل مع الشخصيات الرئيسية في الأفلام. سيتم حقن الخريطة بها ، وتحتوي على أسماء الأفلام بالمفاتيح ، وقيم حبوب الشخصيات الرئيسية:

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

عند بدء التشغيل ، يمكنك أن ترى أن مفتاح Gandalf ليس LOTR ، ولكن gandalf ، يمكننا من خلاله استنتاج أنه لم يكن اسم الفيلم الذي كتب ، ولكن اسم الفول ، في حين أنه في حالة Rimbaud والمنهي كان محظوظًا فقط: أسماء الشخصيات الرئيسية تتزامن مع عناوين الأفلام.

في الواقع ، عندما يكون من الضروري إدخال خريطة ، مفتاحها String ، وقيمة الفاصوليا ، فإن Spring (كما هو الحال في القائمة) سيتجاهل ببساطة الخريطة التي اقترحناها ، ويذهب عبر السياق ويجمع كل الفاصوليا المناسبة s ، وسيتم إنشاء خريطة معهم كقيم وأسمائهم كمفاتيح.

تشبه الحلول البديلة تلك التي عملت مع القائمة:

الخيار 1. عكاز


استبدال الخريطة بـ HashMap:

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

الخيار 2. الأصح


إضافة مؤهل:

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

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


All Articles