深入了解Spring中getBean()的五种方式

 更新时间:2023年02月01日 15:24:11   作者:攻城狮susht  
在本文中,我们将详细介绍从BeanFactory中获取bean的多种方式。简单地说,正如方法的名称所表达的,getBean()负责从Spring IOC容器中获取bean实例,希望对大家有所帮助

1.简介

在本文中,我们将详细介绍从BeanFactory中获取bean的多种方式。

简单地说,正如方法的名称所表达的,getBean()负责从Spring IOC容器中获取bean实例。

2. 创建Bean容器

首先,让我们定义一些用于测试的Spring bean。创建spring IOC容器有多种方式,但是在本文中,我们将使用基于注释的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 {}
}

我们创建了两个bean。Lion具有默认的单例作用域。Tiger被显式地设置为prototype。另外,我们为每个bean定义了名称,这些名称将在后边的实例中使用。

3. getBean() API

BeanFactory提供了getBean()方法的5个方法,我们将在下面的小节中研究。

3.1. 按名称获取Bean

让我们看看如何使用名称获取Lion Bean实例:

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

在此方法中,我们根据bean名称获取bean,如果在spring ico容器中存在和bean,则返回Object 类的实例。否则,抛出如下异常

NoSuchBeanDefinitionException。

主要的缺点是,在获取bean之后,我们必须将它转换为所需的类型。如果返回的bean的类型与我们期望的不同,则可能会产生异常。

假设我们试图用“tiger”这个名字来得到“lion”。当我们将结果转换为lion时,它会抛出一个ClassCastException:

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

3.2.通过名称和类型获取Bean

在这里,我们需要指定所请求bean的名称和类型:

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

与3.1的方法相比,此方法更安全,因为我们可以编译阶段就发现错误而不是在运行阶段。

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。即在同一个IOC 容器中,如果有相同类型的多个bean,则不能通过类型获取bean。

3.4. 按名称和构造函数参数对Bean进行筛选

除了bean名称,我们还可以传递构造函数参数:

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

这个方法有点不同,因为它只适用于具有原型作用域的bean。

在单例的情况下,我们将得到BeanDefinitionStoreException异常。

因为原型bean,每次从spring ioc容器中获取bean都会返回一个新创建的实例,所以我们可以在调用getBean()时动态地提供构造函数参数:

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

正如我们所看到的,根据我们在请求bean时指定的第二个参数,每个Tiger都有不同的名称。

3.5. 按类型和构造函数参数对Bean进行筛选

此方法类似于上一个方法,但是我们需要将类型而不是名称作为第一个参数传递:

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

与3.4相似,此方法仅适用于具有原型作用域的bean。

4.使用注意事项

getBean()尽管是在BeanFactory接口中定义的,但是getBean()方法大部分是通过ApplicationContext访问。通常,我们在应用程序中不希望直接使用getBean()方法。

Bean应该由容器管理。如果我们想使用它们中的一个,我们应该依赖依赖注入,而不是直接调用ApplicationContext.getBean()。这样,我们就可以避免将应用程序逻辑与与框架相关的细节混合在一起。

5.结论

在本快速教程中,我们从BeanFactory接口浏览了getBean() 方法的所有实现,并描述了每种方法的优缺点。

到此这篇关于深入了解Spring中getBean()的五种方式的文章就介绍到这了,更多相关Spring getBean内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • shiro实现单点登录(一个用户同一时刻只能在一个地方登录)

    shiro实现单点登录(一个用户同一时刻只能在一个地方登录)

    这篇文章主要介绍了shiro实现单点登录(一个用户同一时刻只能在一个地方登录)的相关资料,非常不错,具有参考借鉴价值,感兴趣的朋友一起学习吧
    2016-08-08
  • Java线程休眠的5种方法

    Java线程休眠的5种方法

    这篇文章主要介绍了Java线程休眠的5种方法,分别是Thread.sleep、TimeUnit、wait、Condition、LockSupport,下面文章将对这五种方法进行详细讲解,需要的小伙伴可以参考一下
    2022-05-05
  • Java使用MulticastSocket实现群聊应用程序

    Java使用MulticastSocket实现群聊应用程序

    这篇文章主要为大家详细介绍了Java使用MulticastSocket实现群聊应用程序,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-05-05
  • Java并发工具辅助类代码实例

    Java并发工具辅助类代码实例

    这篇文章主要介绍了Java并发工具辅助类代码实例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-04-04
  • spring是如何解析xml配置文件中的占位符

    spring是如何解析xml配置文件中的占位符

    这篇文章主要介绍了spring是如何解析xml配置文件中的占位符,帮助大家更好的理解和使用spring框架,感兴趣的朋友可以了解下
    2020-11-11
  • Java从List中删除元素的几种方式小结

    Java从List中删除元素的几种方式小结

    在Java中,List 接口提供了一个 remove(Object o) 方法来移除列表中与给定对象相等的第一个元素,然而,直接使用这个方法来删除列表中的元素有时并不是最优的选择,主要原因包括效率和同步性问题,本文介绍了Java从List中删除元素的几种方式,需要的朋友可以参考下
    2024-08-08
  • JavaWeb项目中dll文件动态加载方法解析(详细步骤)

    JavaWeb项目中dll文件动态加载方法解析(详细步骤)

    这篇文章主要介绍了JavaWeb项目中dll文件动态加载方法,步骤详细,在这里分享给大家,需要的朋友可以了解下。
    2017-09-09
  • 浅谈JVM系列之JIT中的Virtual Call

    浅谈JVM系列之JIT中的Virtual Call

    什么是Virtual Call?Virtual Call在java中的实现是怎么样的?Virtual Call在JIT中有没有优化?所有的答案看完这篇文章就明白了。
    2021-06-06
  • springboot实现定时任务的四种方式小结

    springboot实现定时任务的四种方式小结

    本文主要介绍了springboot实现定时任务的四种方式小结,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-01-01
  • java设计模式之简单工厂模式

    java设计模式之简单工厂模式

    这篇文章主要为大家详细介绍了java设计模式之简单工厂模式,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2016-12-12

最新评论