zoukankan      html  css  js  c++  java
  • Spring5源码分析(022)——IoC篇之bean加载:FactoryBean的用法

    注:《Spring5源码分析》汇总可参考:Spring5源码分析(002)——博客汇总


      上一篇主要是粗略地分析了 Spring 加载 bean 的整个过程,并没有太多细致的解析,而其中前面几个处理步骤中则反复提及到了 FactoryBean ,本篇将就此小知识进行讲解,目录结构如下:

    1、FactoryBean 的用法

      一般情况下,Spring 是通过反射机制利用 bean 的 class 属性指定的实现类来实例化 bean 的。在某些情况下,实例化 bean 过程比较复杂,如果按照传统的方式,则需要在 bean 中提供大量的配置信息,配置方式的灵活性是受限的,这时候采用编码的方式可能会得到一个简单的方案(当然如果有大量这样的处理的话,灵活性也同样有限,当作是一种补充就行)。Spring 为此提供了一个 org.springframework.beans.factory.FactoryBean 的工厂类接口,用户可以通过实现该接口定制实例化 bean 的逻辑。

      FactoryBean 接口对于 Spring 框架来说占有重要的地位, Spring 本身就提供了70多个 FactoryBean 实现类。他们隐藏了实例化一些复杂 bean 的细节,给上层应用带来了便利。从 Spring3.0 开始, FactoryBean 开始支持泛型,即接口声明改为 FactoryBean<T> 的形式:

    public interface FactoryBean<T> {
    
        T getObject() throws Exception;
    
        Class<?> getObjectType();
    
        default boolean isSingleton() {
            return true;
        }
    
    }

      该接口中定义了3个方法:

    • T getObject()
      • 返回由 FactoryBean 创建的 bean 实例,如果 isSingleton() 返回 true ,则该实例会放到 Spring 容器的单例缓存池中。
    • Class<?> getObjectType()
      • 返回 FactoryBean 创建的 bean 类型
    • boolean isSingleton()
      • 返回由 FactoryBean 创建的 bean 实例的作用域是 singleton 还是 prototype ,默认是单例 singleton ,即返回 true 。

      当配置文件中 <bean> 的 class 属性配置的实现类是 FactoryBean 时,通过 getBean() 方法返回的不是 FactoryBean 本身,而是 FactoryBean#getObject() 方法所返回的对象,相当于代理了 getBean() 方法。例如,如果使用传统方式配置下面的 Car 的 <bean> 时,Car 的每个属性则需要分别对应一个 <property> 元素标签:

    public class Car {
        private int maxSpeed;
        private String brand;
        private double price;
        // setter and getter ...
    }

      如果使用的是 FactoryBean 的方式来实现,则可以灵活配置,例如下面通过逗号分隔符的方式一次性地为 Car 的所有属性指定配置值:

    public class CarFactoryBean implements FactoryBean<Car> {
    
       private String carInfo;
    
       @Override
       public Car getObject() throws Exception {
          Car car = new Car();
          String[] infos = carInfo.split(",");
          car.setBrand(infos[0]);
          car.setMaxSpeed(Integer.valueOf(infos[1]));
          car.setPrice(Double.valueOf(infos[2]));
          return car;
       }
    
       @Override
       public Class<Car> getObjectType() {
          return Car.class;
       }
    
       @Override
       public boolean isSingleton() {
          return false;
       }
    
       public String getCarInfo() {
          return this.carInfo;
       }
    
       // 接收逗号分隔符设置属性信息
       public void setCarInfo(String carInfo) {
          this.carInfo = carInfo;
       }
    } 

      有了这个 CarFactoryBean 之后,就可以在配置文件中使用下面这种自定义的配置方式了:

    <bean id="carBean" class="cn.wpbxin.bean.CarFactoryBean">
        <property name="carInfo" value="超跑,400,2000000" />
    </bean>

      当调用 getBean("carBean") 时,Spring 通过反射机制发现 CarFactoryBean 实现了 FactoryBean 的接口,这时 Spring 容器就调用接口方法 CarFactoryBean#getObject() 方法返回。如果希望获取 CarFactoryBean 实例,则需要在使用 getBean(beanName) 时在 beanName 签加上 “&” 前缀,例如 getBean("&carBean"),表示需要获取 FactoryBean 实例本身,也就是 CarFactoryBean 本身。

    2、参考

  • 相关阅读:
    《leetcode42接雨水》
    《84. 柱状图中最大的矩形》
    [bzoj1565][NOI2009]植物大战僵尸
    [bzoj1497][NOI2006]最大获利
    [洛谷P4092][HEOI2016/TJOI2016]树
    [洛谷P3760][TJOI2017]异或和
    [洛谷P3758][TJOI2017]可乐
    [洛谷P3761][TJOI2017]城市
    [Uva11134]Fabled Rooks
    又是一年叶落时
  • 原文地址:https://www.cnblogs.com/wpbxin/p/14903163.html
Copyright © 2011-2022 走看看