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、参考

  • 相关阅读:
    A1023 Have Fun with Numbers (20分)(大整数四则运算)
    A1096 Consecutive Factors (20分)(质数分解)
    A1078 Hashing (25分)(哈希表、平方探测法)
    A1015 Reversible Primes (20分)(素数判断,进制转换)
    A1081 Rational Sum (20分)
    A1088 Rational Arithmetic (20分)
    A1049 Counting Ones (30分)
    A1008 Elevator (20分)
    A1059 Prime Factors (25分)
    A1155 Heap Paths (30分)
  • 原文地址:https://www.cnblogs.com/wpbxin/p/14903163.html
Copyright © 2011-2022 走看看