Noções básicas sobre getBean () no Spring

Noções básicas sobre getBean () no Spring

1. Introdução

Neste tutorial, vamos passar por diferentes variantes do métodoBeanFactory.getBean().

Simplificando, como o nome do método também sugere,thisis responsible for retrieving a bean instance from the Spring container.

2. Configuração do Spring Beans

Primeiro, vamos definir alguns beans Spring para teste. Existem várias maneiras de fornecer definições de bean para o contêiner Spring, mas em nosso exemplo, usaremos a configuração Java baseada em anotação:

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

Criamos dois feijões. Lion tem o escopo singleton padrão. Tiger é explicitamente definido comoprototype scope. Além disso, observe que definimos nomes para cada bean que usaremos em outras solicitações.

3. As APIsgetBean()

BeanFactory fornece cinco assinaturas diferentes do métodogetBean() que examinaremos nas subseções a seguir.

3.1. Recuperando Bean por Nome

Vamos ver como podemos recuperar uma instância de beanLion usando seu nome:

Object lion = context.getBean("lion");

assertEquals(Lion.class, lion.getClass());

Nesta variante, fornecemos um nome e, em troca, obtemos uma instância deObject class se um bean com o nome fornecido existir no contexto do aplicativo. Caso contrário, esta e todas as outras implementações lançamNoSuchBeanDefinitionException se a pesquisa do bean falhar.

A principal desvantagem é queafter retrieving the bean, we have to cast it to the desired type. This may produce another exceptionif the returned bean has a different type than we expected.

Suponha que tentemos obter umTiger usando o nome“lion”.. Quando lançamos o resultado paraTiger, ele lançará umClassCastException:

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

3.2. Recuperando Bean por Nome e Tipo

Aqui precisamos especificar o nome e o tipo do bean solicitado:

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

Comparado ao método anterior, este é mais seguro porque obtemos as informações sobre incompatibilidade de tipos instantaneamente:

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

3.3. Recuperando Bean por Tipo

Com a terceira variante degetBean(),, é suficiente especificar apenas o tipo de feijão:

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

Nesse caso, precisamospay special attention to a potentially ambiguous outcome:

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

No exemplo acima, comoLion eTiger implementam a interfaceAnimal, apenas especificar o tipo não é suficiente para determinar o resultado de forma inequívoca. Portanto, obtemos umNoUniqueBeanDefinitionException.

3.4. Recuperando Bean por Nome com Parâmetros do Construtor

Além do nome do bean, também podemos passar parâmetros do construtor:

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

This method is a bit different because it only applies to beans with prototype scope.

No caso de singletons, vamos obter umBeanDefinitionStoreException.

Como um bean de protótipo retornará uma instância recém-criada toda vez que for solicitado do contêiner do aplicativo,we can provide constructor parameters on-the-fly ao invocargetBean():

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

assertEquals("Siberian", tiger.getName());
assertEquals("Striped", secondTiger.getName());

Como podemos ver, cadaTiger recebe um nome diferente de acordo com o que especificamos como um segundo parâmetro ao solicitar o bean.

3.5. Recuperando Bean por Tipo com Parâmetros do Construtor

Este método é análogo ao último, mas precisamos passar o tipo em vez do nome como o primeiro argumento:

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

assertEquals("Shere Khan", tiger.getName());

Semelhante a recuperar um bean por nome com parâmetros do construtor,this method only applies to beans with prototype scope.

4. Considerações de uso

Apesar de estar definido na interfaceBeanFactory, o métodogetBean() é acessado com mais frequência por meio deApplicationContext. Normalmente,we don’t want to use the getBean() method directly in our program.

O feijão deve ser gerenciado pelo contêiner. Se quisermos usar um deles, devemos contar comdependency injection em vez de uma chamada direta paraApplicationContext.getBean().. Dessa forma, podemos evitar misturar a lógica do aplicativo com detalhes relacionados ao framework.

5. Conclusão

Neste tutorial rápido, passamos por todas as implementações do métodogetBean() da interfaceBeanFactory e descrevemos os prós e contras de cada uma.

Todos os exemplos de código mostrados aqui estão disponíveisover on GitHub.