目录

1.Spring 容器初始化

 2.Spring Bean 初始化

2.1 BeanFactory 和 FactoryBean

2.2 Bean 的实例化



1.Spring 容器初始化

       在 Spring 中,不管是以 XML 文件的方式配置的 Bean 还是以注解的方式进行配置,最后都会将单例Bean放入到Spring的容器中,这里说的单例池不是说放入的Bean都是单例的,而是spring在单例池中的Bean都是单例的,只要你从单例池中取Bean对象,那么整个生命周期过程中都只有一个实例,但是你放入单例池的对象Bean它不是单例的,你可以不借助spring而自己产生多例,但是一般都没有这么做,只是时候在概念上要理解单例池和单例类的区别,spring容器的整个启动到初始化过程如下:

spring boot 初始化List对象 spring怎么初始化bean_实例化

 2.Spring Bean 初始化

       在 Spring 容器中有两种 Bean,一种是普通的 Bean,一种是 FactoryBean。在介绍 Bean 的初始化之前,我们要先来理解这两种 Bean 的区别。

2.1 BeanFactory 和 FactoryBean

        BeanFactory 是 Spring 的容器中的 Bean 工厂,Bean 的创建、获取都是它来完成的,也就是说 BeanFactory 就是 Spring 的容器,里面放入了所有的 Bean,包括单例 Bean、原型的 Bean 定义(BeanDefinition)。而 FactoryBean 也是一种 Bean,FactoryBean 是 BeanFactory 的一种 Bean,是一种特殊的 Bean,FactoryBean 中是只能放入一种类型的 Bean,而 BeanFactory 中可以放入不同类型的 Bean,我们先来看下 FactoryBean 接口提供的方法,也就是它本身定义了提供了那些功能:

public interface FactoryBean<T> {

    @Nullable
    T getObject() throws Exception;

    @Nullable
    Class<?> getObjectType();

    default boolean isSingleton() {
       return true;
}

(1)getObject()方法

        返回的是由 FactoryBean 创建的 Bean 实例,也就当 getBean() 的时候,返回的就是 Spring 调用 getObject() 返回的 Bean 对象。如果 isSingleton() 返回 true,则该实例会放到 Spring 容器的单实例缓存池中。

(2)getObjectType()方法

        返回 FactoryBean 创建的 Bean 的类型。

(3)isSingleton()方法

        确定由 FactoryBean 创建的 Bean 的作用域是 singleton 还是prototype。该方法是 FactoryBean 的默认方法,默认为单例的 bean。

下面简单看下 FactoryBean 的例子,

     

spring boot 初始化List对象 spring怎么初始化bean_初始化_02

    

spring boot 初始化List对象 spring怎么初始化bean_java_03

    

spring boot 初始化List对象 spring怎么初始化bean_初始化_04

spring boot 初始化List对象 spring怎么初始化bean_java_05

       输出的是 Person 对象,所以 FactoryBean 获取 Bean 返回的是 geteObject 返回的对象,在 spring 容器中存在两个 Bean,一个是 FactoryBean 对应的对象,一个是 FactoryBean 中 getObject 返回的对象。而且如果通过 act.getBean(“bmlFactoryBean”) 不管获取几次都是相同的对象,这里有一个重要的概念,我们都知道 FactoryBean 创建的对象默认都是单例 Bean,但是一般的 @Coponent 创建的 Bean 和 FactoryBean 创建的对象有什么不同吗?
其实在上面的代码中,User对象的真正创建不是在65行代码,而是在66或67行代码,虽然我们的 FactoryBean 默认是单例的,但是 FactoryBean 只有在第一次 getBean 的时候才会放入到单例池,也就是说 FactoryBean 默认是懒加载的。
      而在 spring 容器中最终会出现两个 Bean,比如就上面的代码,那么 beanName=bmlFactoryBean 是对应的我们的Person Bean对象,而 beanName=&bmlFactoryBean 对应的是我们的 FactoryBean 本身的 Bean 对象。
 

spring boot 初始化List对象 spring怎么初始化bean_后端_06

      看上图,其中 BeanFactory 中的单例池是 singletonObjects ,里面存放的是加了 @Component 注解的单例 Bean,而上面的代码的 FactoryBean 是放在了单例池中的,而 FactoryBean 中 getObject 方法返回的对象的 Bean 是放在了 factoryBeanOjectCache 中的。我们通过 ApplicationContext 的 getBean 去获取 FactoryBean 的时候,如果 beanName 前面加了&就表示获取本身的 FactoryBean,而不加&则表示获取 FactoryBean 中的 getObject 返回的对象。
 

2.2 Bean 的实例化

     Bean 的实例化时机分为两种:BeanFactory 管理的 Bean 是在使用到 Bean 的时候才会实例化 Bean(懒加载),ApplicationContext 管理的 Bean 在容器初始化的时候就会完成 Bean 实例化。