1.Bean的类型

1.1 普通Bean

  1. @Component
  2. public class Child {
  3. }
  1. @Bean
  2. public Child child() {
  3. return new Child();
  4. }
  1. <bean class="com.linkedbear.spring.bean.a_type.bean.Child"/>

1.2 FactoryBean

顾名思义是用工厂方法创建Bean
FactoryBean 本身是一个接口,它本身就是一个创建对象的工厂。如果 Bean 实现了 FactoryBean 接口,则它本身将不再是一个普通的 Bean ,不会在实际的业务逻辑中起作用,而是由创建的对象来起作用。
FactoryBean 接口有三个方法:

  1. public interface FactoryBean<T> {
  2. // 返回创建的对象
  3. @Nullable
  4. T getObject() throws Exception;
  5. // 返回创建的对象的类型(即泛型类型)
  6. @Nullable
  7. Class<?> getObjectType();
  8. // 创建的对象是单实例Bean还是原型Bean,默认单实例
  9. default boolean isSingleton() {
  10. return true;
  11. }
  12. }

2.Bean的作用域

2.1SpringFramework中内置的作用域

SpringFramework 中内置了 6 种作用域(5.x 版本):

作用域类型 概述
singleton 一个 IOC 容器中只有一个【默认值】
prototype 每次获取创建一个
request 一次请求创建一个(仅Web应用可用)
session 一个会话创建一个(仅Web应用可用)
application 一个 Web 应用创建一个(仅Web应用可用)
websocket 一个 WebSocket 会话创建一个(仅Web应用可用)

2.2 singleton:单实例Bean

SpringFramework 官方文档中有一张图,解释了单实例 Bean 的概念:
image.png
左边的几个定义的 Bean 同时引用了右边的同一个 accountDao ,对于这个 accountDao 就是单实例 Bean 。
SpringFramework 中默认所有的 Bean 都是单实例的,即:一个 IOC 容器中只有一个。下面咱演示一下单实例 Bean 的效果:

2.3 prototype 原型Bean

Spring 官方的定义是:每次对原型 Bean 提出请求时,都会创建一个新的 Bean 实例。这里面提到的 ”提出请求“ ,包括任何依赖查找、依赖注入的动作,都算做一次 ”提出请求“ 。由此咱也可以总结一点:如果连续 getBean() 两次,那就应该创建两个不同的 Bean 实例;向两个不同的 Bean 中注入两次,也应该注入两个不同的 Bean 实例。SpringFramework 的官方文档中也给出了一张解释原型 Bean 的图:

image.png
其实对于原型这个概念,在设计模式中也是有对应的:原型模式。原型模式实质上是使用对象深克隆,乍看上去跟 SpringFramework 的原型 Bean 没什么区别,但咱仔细想,每一次生成的原型 Bean 本质上都还是一样的,只是可能带一些特殊的状态等等,这个可能理解起来比较抽象,可以跟下面的 request 域结合着理解。

2.3.1 修改Bean的类型

给 Toy 的类上标注一个额外的注解:@Scope ,并声明为原型类型:

  1. @Component
  2. @Scope("prototype")
  3. public class Toy {
  4. }

注意,这个 prototype 不是随便写的常量,而是在 ConfigurableBeanFactory 中定义好的常量:

  1. public interface ConfigurableBeanFactory extends HierarchicalBeanFactory, SingletonBeanRegistry {
  2. String SCOPE_SINGLETON = "singleton";
  3. String SCOPE_PROTOTYPE = "prototype";

如果真的担心打错,建议引用该常量  ̄へ ̄ 。。。

2.4 web应用的作用域

上面表中还涉及到几个关于 Web 应用的作用域,它们都是在 Web 应用中才会有的,这个咱放到后面介绍 SpringWebMvc 时再介绍,这里只是简单介绍一下。

  • request :请求Bean,每次客户端向 Web 应用服务器发起一次请求,Web 服务器接收到请求后,由 SpringFramework 生成一个 Bean ,直到请求结束
  • session :会话Bean,每个客户端在与 Web 应用服务器发起会话后,SpringFramework 会为之生成一个 Bean ,直到会话过期
  • application :应用Bean,每个 Web 应用在启动时,SpringFramework 会生成一个 Bean ,直到应用停止(有的也叫 global-session )
  • websocket :WebSocket Bean ,每个客户端在与 Web 应用服务器建立 WebSocket 长连接时,SpringFramework 会为之生成一个 Bean ,直到断开连接

上面 3 种可能小伙伴们还熟悉,最后一种 WebSocket 可能有些小伙伴还不了解,不了解没关系,这玩意用的也少,等回头小伙伴学习了 WebSocket 之后自己试一下就可以了,小册这里也不多展开了。

3.Bean实例化的方式

3.1普通Bean实例化

其实咱前面创建的所有 标签、@Bean 注解的方式,都是普通 Bean 的对象,它们默认是单实例的,在 IOC 容器初始化时就已经被初始化了。咱已经足够熟悉了,不多赘述。

3.2 FactoryBean创建Bean

3.3 使用静态工厂创建Bean

3.4 借助实例工厂创建Bean

注:【面试题】BeanFactory与FactoryBean的区别

以下答案仅供参考,可根据自己的理解调整回答内容:
BeanFactory :SpringFramework 中实现 IOC 的最底层容器(此处的回答可以从两种角度出发:从类的继承结构上看,它是最顶级的接口,也就是最顶层的容器实现;从类的组合结构上看,它则是最深层次的容器,ApplicationContext 在最底层组合了 BeanFactory )
FactoryBean :创建对象的工厂 Bean ,可以使用它来直接创建一些初始化流程比较复杂的对象