Spring学习笔记:Spring容器中查找Bean的方式

本文是自己学习的一个总结


1、Spring容器中查找Bean的方式

1.1、查找单一的bean

1.1.1、根据bean名称实时查找bean

getBean(String)这个方法很常见,所以的容器都具有这个方法。容器中可直接通过bean的名称查找bean

User user = (User) applicationContext.getBean("user");



1.1.2、根据bean类型查找

getBean(String)有个重载形式是getBean(Class),这个可以根据类型查找bean。只是要注意,如果容器内没有这种类型的bean,或者容器内这种类型的bean不止一个,那这个方法会报错。

User user = applicationContext.getBean(User.class);

1.1.3、根据ObjectFactory查找bean(延迟查找)

我们可以借助ObjectFactory来间接获取bean。ObjectFactory是一个接口,这个接口定义了工厂查找bean的一个规范。其中有一个getObject()方法,这个方法就是用于获取bean的。

我们在xml中定义ObjectFactory的一个实现类,令targetName指向容器内的一个bean。

<bean id="objectFactory" class="org.springframework.beans.factory.config.ObjectFactoryCreatingFactoryBean" p:targetBeanName="user"/>

其中user是容器中已经定义好的一个bean的id。

之后我们可以这样获取user。

ObjectFactory<User> objectFactory = (ObjectFactory<User>) beanFactory.getBean("objectFactory");
User user = objectFactory.getObject();

ObjectFactory之所以是延迟查找,是因为一开始容器中是只有objectFactory这么一个bean,我们真正想要的bean(user)并没有被实例化。一直等到objectFactory.getObject()执行的时候才开始实例化user。

1.1.4、延迟查找(ObjectProvider)

这里的延迟查找是通过ObjectProvider这个接口。ObjectProvider和ObjectFactory有些类似,先生成一个中间对象,这个对象托管者我们真正想要的bean。两者都是很相似,毕竟ObjectProvider是直接继承于ObjectFactory的。

在这里插入图片描述
在ApplicationContext中可以通过下面这个接口获取到ObjectProvider。

  • ObjectProvider getBeanProvider(Class requiredType);
    这个接口是获取到一个ObjectProvider,这个ObjectProvider中托管着容器中类型为requiredType的bean。
    得到ObjectProvider之后,我们就可以通过getObject(),getIfUnique()等方法获取到对应的bean。

需要注意的一点是,因为ObjectProvider是通过类型获取的,和其他通过类型获取bean的方法一样,获取的时候要保证该类型的bean在容器中是唯一存在的,或者容器中同一类型的bean有多个,但是都有规定好qualifier或者primary来保证唯一性。

我们看看例子。

public class Test {
    public static void main(String[] args) {
        ApplicationContext applicationContext = new AnnotationConfigApplicationContext(Test.class);
        ObjectProvider<String> objectProvider = applicationContext.getBeanProvider(String.class);
        System.out.println(objectProvider.getObject());
    }
    @Bean
    public String helloWorld() {
        return "Hello world!";
    }
}

这段代码可以运行,会输出Hello world!。
但是如果根据类型不能确定唯一的bean,结果可能会达不到我们的预期。比如下面的代码。

public class Test {
    public static void main(String[] args) {
        ApplicationContext applicationContext = new AnnotationConfigApplicationContext(Test.class);
        ObjectProvider<String> objectProvider = applicationContext.getBeanProvider(String.class);
        System.out.println(objectProvider.getObject());
    }
    @Bean
    public String helloWorld() {
        return "Hello world!";
    }
    
    @Bean
    public String HelloEveryone() {
        return "Hello everyOne";
    }
}

这段代码运行会报错。
在这里插入图片描述




1.2、查找多个bean

查找多个bean需要依赖ListableBeanFactory。从名字上看,Listable,可罗列的可列表化的,就表明这个beanFactory在查找的时候可以应用在集合接口。

1.2.1、根据bean类型查找

1.2.1.1、获取同类型bean名称列表

获取容器内特定类型的所有bean的名称,有个接口可以实现这个效果。

  • String[] getBeanNamesForType(Class)
1.2.1.2、获取同类型bean的实例列表
  • Map<String, T> getBeansOfType(Class)

我们可以通过getBeansOfType来查找特定类型的多个bean。该方法会查找到容器中类型为指定类型的bean,返回只是一个map,key为bean的id,value为bean实例。

ListableBeanFactory listableBeanFactory = (ListableBeanFactory) beanFactory;
Map<String, User> users = listableBeanFactory.getBeansOfType(User.class);



1.2.2、根据注解查找

与通过类型查找一样,有获取bean名称的,也有获取bean实例的

1.2.2.1、根据注解查找bean名称

我们可以查找容器内所有被某个注解标注的所有的bean的名词,使用getBeanNamesForAnnotation这个方法。这个方法也是在ListableBeanFactory中才有。


1.2.2.2、根据注解查找bean实例

我们可以查找容器内所有被某个注解标注的所有的bean,使用getBeansWithAnnotation这个方法。这个方法也是在ListableBeanFactory中才有。

ListableBeanFactory listableBeanFactory = (ListableBeanFactory) beanFactory;
Map<String, User> users = (Map) listableBeanFactory.getBeansWithAnnotation(Super.class);

users中存储的就是所有被@Super这个注解标注的bean。


1.2.3、同时根据名称和注解查找

  • findAnnotationOnBean(String, Class)

1.3、层次性依赖查找

1.3.1、什么是层次性依赖查找

层次性依赖查找,也就是双亲委派。这个双亲委派的意义和类加载机制中的双亲委派一样——简单来说就是当一个类加载器准备加载一个类时,会将这个加载任务交给它的父类加载器。如果这个父类加载器还有父类,那它也会将这个任务交给它的父类去做,就这样不断递归······直到任务委派到根父类,这时候如果父类无法完成加载任务,那子类才会去尝试加载。

容器中也有父子关系。双亲委派查找就是子类会优先将查找任务交给父类容器,父类容器找不到对应bean后,子类容器才会去查找。


1.3.2、HierarchicalBeanFactory

首先我们看看HierarchicalBeanFactory这个接口。它继承BeanFactory,有两个方法。在这里插入图片描述
第一个getParentBeanFactory()很明显是用来获取父类容器的。

第二个containsLocalBean(String name)是用来查看当前容器中是否包含名称为name的bean。localBean的意思就是当前容器中的bean,不包括父类容器的bean。注释中也说明了只在当前容器中查找,忽略父类容器中的bean。

有一点可以放心,所有的容器实现类都直接或者间接继承了HierarchicalBeanFactory。比如ApplicationContext就是直接继承了这个接口,那可以推断,所有的ApplicationContext都支持上面的两个方法。
在这里插入图片描述




1.3.3、设置父容器

设置父容器的方法是setParentBeanFactory(BeanFactory parentBeanFactory)。要注意这个方法是在ConfigurableBeanFactory中定义的,只有其继承者才有这个方法来设置父容器。

ApplicationContext没有继承ConfigurableBeanFactory这个接口,所以ApplicationContext和它的实现类都不能设置父容器。
在这里插入图片描述
这里就会有疑问了,既然ApplicationContext都不支持设置父容器,那它继承HierarchicalBeanFactory干嘛?

其实ApplicationContext是支持父容器的,并且也是通过ConfigurableBeanFactory定义的setParentBeanFactory来设置。要理解这句话那就要先了解ApplicationContext和BeanFactory之间的关系。

在这篇文章的开头介绍了ApplicationContext和BeanFactory之间的关系。
https://blog.csdn.net/sinat_38393872/article/details/105918728

在这里插入图片描述

表面上看,ApplicationContext是继承BeanFactory,但实际上两者的关系是代理模式。ApplicationContext需要实现容器的基本功能时,就会拉出其内部持有的BeanFactory类型的成员变量,让这个beanFactory来实现那些基本的容器功能,然后ApplicationContext再稍微润色一下。

代理模式看这篇文章:https://blog.csdn.net/sinat_38393872/article/details/106316008

真正具有容器层次性的是BeanFactory而不是ApplicationContext。当我们说给ApplicationContext设置父容器时,是指给ApplicationContext内部持有的BeanFactory成员变量设置父容器。

下面代码分别展示了给ApplicationContext和BeanFactory设置父容器

//给BeanFactory设置父容器
BeanFactory parentBeanFactory = new XmlBeanFactory(resource1);
DefaultListableBeanFactory sonBeanFactory = new XmlBeanFactory(resource2);
//设置好之后sonBeanFactory就可以查找到parentBeanFactory中的bean
sonBeanFactory.setParentBeanFactory(parentBeanFactory);

//给ApplicationContext设置父容器
ConfigurableApplicationContext sonApplicationContext = new ClassPathXmlApplicationContext("路径");
//设置好之后sonApplicationContext就可以查找到parentBeanFactory中的bean
sonApplicationContext.getBeanFactory().setParentBeanFactory(parentBeanFactory);



  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 很高兴听到您对Spring Boot 2的学习感兴趣。Spring Boot是一个基于Spring框架的快速开发应用程序的工具,它提供了一种简单的方式来创建和配置Spring应用程序。以下是一些学习Spring Boot 2的笔记: 1. Spring Boot 2的新特性:Spring Boot 2相对于Spring Boot 1.x版本来说,有许多新的特性和改进。例如,它支持Java 9和10,提供了更好的响应式编程支持,以及更好的安全性和监控功能。 2. Spring Boot 2的核心组件:Spring Boot 2的核心组件包括Spring Framework、Spring MVC、Spring Data和Spring Security等。这些组件提供了一系列的功能和工具,使得开发人员可以更加轻松地构建和管理应用程序。 3. Spring Boot 2的配置:Spring Boot 2的配置非常简单,它提供了一种基于注解的方式来配置应用程序。开发人员可以使用@Configuration和@Bean注解来定义配置类和Bean。 4. Spring Boot 2的启动器:Spring Boot 2提供了一系列的启动器,这些启动器可以帮助开发人员快速地集成各种常用的框架和库,例如Spring Data JPA、Spring Security、Thymeleaf等。 5. Spring Boot 2的测试:Spring Boot 2提供了一系列的测试工具,例如Spring Boot Test、Mockito、JUnit等。这些工具可以帮助开发人员编写高质量的单元测试和集成测试。 希望这些笔记对您学习Spring Boot 2有所帮助。如果您有任何问题或疑问,请随时联系我。 ### 回答2: Spring Boot 是一个非常流行的开源框架,它的目的是使 Spring 应用程序的开发过程更加简单、快速和高效。Spring Boot 2 是 Spring Boot 框架的第二个版本,已经成为了当今业界最流行的 Java 开发框架之一。 Spring Boot 2 的新特性: 1. 支持 JDK 9。Spring Boot 2 已经支持 JDK 9 所带来的新特性和功能。 2. 基于 Reactive Streams 的编程模型。Spring Boot 2 增加了对 Reactive Streams 的支持,可以开发响应式应用程序,从而提高了系统的吞吐量和性能。 3. 异步服务器支持。Spring Boot 2 已经支持多种异步服务器,包括 Netty、Undertow 和 Tomcat。 4. 更全面的 Actuator 组件。Actuator 是 Spring Boot 的监控和管理组件,Spring Boot 2 在 Actuator 组件上增加了更多的指标、健康检查和应用程序信息。 5. 更好的自定义配置。Spring Boot 2 简化了自定义配置的流程,使得用户可以更快速地配置应用程序。 学习 Spring Boot 2 的步骤如下: 1. 掌握 Spring 基础知识。学习 Spring Boot 2 前需要掌握 Spring MVC、Spring Data 等相关的知识。 2. 下载安装 Spring Boot。Spring Boot 2 可以在官网上下载。 3. 学习 Spring Boot 核心组件。包括 Spring IoC、Spring AOP、Spring MVC 等核心组件。 4. 开发一个 Spring Boot 应用程序。可以从一个简单的 Hello World 开始,逐渐增加功能,学习和理解 Spring Boot 的各种特性和功能。 5. 掌握 Spring Boot 的自动配置。Spring Boot 的自动配置可以大大减少开发人员的工作量,学习和掌握自动配置非常重要。 总之,学习 Spring Boot 2 需要不断地实践和探索,只有通过实际的开发经验才能真正掌握和学会这个框架。 ### 回答3: Spring Boot是一款基于Spring框架的快速应用开发框架。在应用开发的过程Spring Boot可以自动配置一个相对完整的Spring应用程序,从而大大减少了开发者的工作量,提高了开发效率。显然,它的学习是很有必要的。 Spring Boot 2.x版本相比于1.x版本在很多方面都进行了升级和改进。在学习的过程,需要关注的重点在以下几点: 1. 新建Spring Boot项目 Spring Boot提供了Spring Initializr来快速创建新的Spring Boot项目。在构建项目的过程,我们可以自定义项目的基本信息、项目类型、依赖关系等,可以根据需求灵活选择。 2. Spring Boot自动配置 Spring Boot借助于自动配置功能,可以为开发者免去大量的配置工作。Spring Boot把一些常用的配置提取为Starter,开发者只需要引入这些Starter即可实现自动配置,大大降低了开发成本。 3. Spring Boot集成 Spring Boot集成了众多流行的框架,如MyBatis、Hibernate、JPA、Thymeleaf等,只需要简单的配置就可以实现对这些框架的集成,使得在开发更加方便。 4. Spring Boot监控管理 Spring Boot通过Actuator提供了一系列配置和管理服务,可以实现对Spring Boot应用程序的监控和管理。开发者可以通过这些服务来监控应用程序的运行状态、访问量、资源使用情况等。 5. Spring Boot测试 Spring Boot天生适合进行单元测试和集成测试,可以使用JUnit、Mockito、Spring Test等框架进行测试。同样可以利用Spring Boot提供的Test Starter进行自动配置,减少测试的开发成本。 以上就是Spring Boot 2的一些学习笔记,它的结构简洁,代码清晰,便于开发者使用。无疑,Spring Boot 2是一个非常适合作为开发者日常工作的框架。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值