Разбиране на getBean () през пролетта

1. Въведение

В този урок ще преминем през различни варианти на метода BeanFactory.getBean () .

Просто казано, както подсказва и името на метода, това е отговорно за извличане на екземпляр на боб от контейнера Spring .

2. Настройка на Spring Beans

Първо, нека дефинираме няколко пролетни зърна за тестване. Има няколко начина, по които можем да предоставим дефиниции на компоненти за контейнера Spring, но в нашия пример ще използваме Java конфигурация, базирана на анотации:

@Configuration class AnnotationConfig { @Bean(name = {"tiger", "kitty"}) @Scope(value = "prototype") Tiger getTiger(String name) { return new Tiger(name); } @Bean(name = "lion") Lion getLion() { return new Lion("Hardcoded lion name"); } interface Animal {} } 

Създадохме два боб. Lion има единичен обхват по подразбиране. Tiger е изрично настроен на обхват на прототипа. Освен това, имайте предвид, че определихме имена за всеки боб, който ще използваме при допълнителни заявки.

3. API на getBean ()

BeanFactory предоставя пет различни подписа на метода getBean () , които ще разгледаме в следващите подраздели.

3.1. Извличане на Bean по име

Нека да видим как можем да извлечем екземпляр на боб Lion, използвайки неговото име:

Object lion = context.getBean("lion"); assertEquals(Lion.class, lion.getClass());

В този вариант ние предоставяме име, а в замяна получаваме екземпляр от клас Object, ако в контекста на приложението съществува боб с даденото име. В противен случай и тази, и всички други реализации хвърлят NoSuchBeanDefinitionException, ако търсенето на боб не успее.

Основният недостатък е, че след извличането на зърното трябва да го хвърлим към желания тип. Това може да доведе до друго изключение, ако върнатият боб има различен тип, отколкото очаквахме .

Да предположим, че се опитваме да получим Тигър, използвайки името „лъв“. Когато предадем резултата на Tiger , той ще хвърли ClassCastException :

assertThrows(ClassCastException.class, () -> { Tiger tiger = (Tiger) context.getBean("lion"); });

3.2. Извличане на Bean по име и тип

Тук трябва да посочим както името, така и типа на искания боб:

Lion lion = context.getBean("lion", Lion.class);

В сравнение с предишния метод, този е по-безопасен, защото получаваме незабавно информацията за несъответствието на типа:

assertThrows(BeanNotOfRequiredTypeException.class, () -> context.getBean("lion", Tiger.class)); }

3.3. Извличане на Bean по тип

С третия вариант на getBean () е достатъчно да посочите само типа bean:

Lion lion = context.getBean(Lion.class);

В този случай трябва да обърнем специално внимание на потенциално двусмислен резултат :

assertThrows(NoUniqueBeanDefinitionException.class, () -> context.getBean(Animal.class)); }

В горния пример, тъй като и Lion, и Tiger прилагат интерфейса Animal , само посочването на типа не е достатъчно за еднозначно определяне на резултата. Следователно получаваме NoUniqueBeanDefinitionException .

3.4. Извличане на Bean по име с параметри на конструктора

В допълнение към името на боб, можем да предадем и параметри на конструктора:

Tiger tiger = (Tiger) context.getBean("tiger", "Siberian");

Този метод е малко по-различен, защото се прилага само за зърна с обхват на прототипа .

В случая на единични, ще получим BeanDefinitionStoreException.

Тъй като прототипният компонент ще връща новосъздаден екземпляр всеки път, когато бъде заявен от контейнера на приложението, ние можем да предоставим параметри на конструктора в движение, когато извикваме getBean () :

Tiger tiger = (Tiger) context.getBean("tiger", "Siberian"); Tiger secondTiger = (Tiger) context.getBean("tiger", "Striped"); assertEquals("Siberian", tiger.getName()); assertEquals("Striped", secondTiger.getName());

Както можем да видим, всеки Тигър получава различно име според това, което сме посочили като втори параметър при заявяване на боб.

3.5. Извличане на Bean по тип с параметри на конструктора

Този метод е аналогичен на последния, но трябва да предадем типа вместо името като първи аргумент:

Tiger tiger = context.getBean(Tiger.class, "Shere Khan"); assertEquals("Shere Khan", tiger.getName());

Подобно на извличането на боб по име с параметри на конструктора, този метод се прилага само за зърна с обхват на прототип .

4. Съображения за употреба

Въпреки че е дефиниран в интерфейса BeanFactory , методът getBean () е най-често достъпен чрез ApplicationContext. Обикновено не искаме да използваме метода getBean () директно в нашата програма .

Фасулът трябва да се управлява от контейнера. Ако искаме да използваме един от тях, трябва да разчитаме на инжектиране на зависимост, а не на директно извикване на ApplicationContext.getBean () . По този начин можем да избегнем смесването на логиката на приложението с подробности, свързани с рамката.

5. Заключение

В този бърз урок преминахме през всички реализации на метода getBean () от интерфейса BeanFactory и описахме плюсовете и минусите на всеки.

Всички примери за кодове, показани тук, са достъпни в GitHub.