FactoryBean

总结自:https://www.cnblogs.com/davidwang456/p/3688250.html

Spring中有两种类型的Bean,一种是普通Bean,另一种是工厂Bean,即xxxFactoryBean返回的bean

工厂Bean跟普通Bean不同,其不是类的一个实例,而是xxxFactoryBeangetObject方法所返回的xxx的对象(通过getObject返回对象,这是工厂bean的核心!)

如何创建bean?

传统方式,通过反射机制利用bean的class属性指定实现类来实例化bean,这需要大量配置,不甚灵活,

而通过工厂bean,我们能定制实例化bean的流程。

备注:FactoryBean是一个接口,而xxxFactoryBean是实现了FactoryBean的类,可以生成某一个类型Bean实例。

Spring 自身就提供了70多个FactoryBean的实现。它们隐藏了实例化一些复杂bean的细节,给上层应用带来了便利。

从Spring 3.0 开始, FactoryBean开始支持泛型,即接口声明改为FactoryBean<T> 的形式:

package org.Springframework.beans.factory;    
public interface FactoryBean<T> {    
   T getObject() throws Exception;    
   Class<?> getObjectType();    
   boolean isSingleton();    
} 

方法介绍:

T getObject():返回由FactoryBean创建的bean实例,如果isSingleton()返回true,则该实例会放到Spring容器中单实例缓存池中。

boolean isSingleton():返回由FactoryBean创建的bean实例的作用域是singleton还是prototype。

Class<T> getObjectType():返回FactoryBean创建的bean类型。

当配置文件中<bean>的class属性配置的实现类是FactoryBean时,通过 getBean()方法返回的不是FactoryBean的实例,而是FactoryBean的getObject()方法所返回的对象,

这相当于FactoryBean的getObject()代理了getBean()方法

如何体现factoryBean的灵活?

例如:如果使用传统方式配置下面Car的<bean>时,Car的每个属性分别对应一个<property>元素标签

public   class  Car  {    
       private   int maxSpeed ;    
       private  String brand ;    
       private   double price ;    
      //get/set方法...
}

如果使用factoryBean

public   class  CarFactoryBean  implements  FactoryBean<Car>  {    
    private  String carInfo ;    
    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;    
    }    
    public  Class<Car> getObjectType ()   {    
        return  Car. class ;    
    }    
    public   boolean  isSingleton ()   {    
        return   false ;    
    }    
    public  String getCarInfo ()   {    
        return   this . carInfo ;    
    }    
    
    // 接受逗号分割符设置属性信息    
    public   void  setCarInfo ( String carInfo )   {    
        this . carInfocarInfo  = carInfo;    
    }    
}

个人理解,在设值时能有更多的个人操作,相当于通用版和定制化的区别

那么相应的,我们应当这么配置:

<bean id="car" class="com.test.factorybean.CarFactoryBean" carInfo="超级跑车,400,2000000"/> 

注意,这是工厂bean定义bean的一般形式。

当调用getBean("car") 时,Spring首先通过反射机制,发现CarFactoryBean实现了FactoryBean的接口,

然后调用getObject()方法返回定制的car实例。

备注:如果单纯希望获取CarFactoryBean的实例,则需要在使用getBean(beanName) 方法时在beanName前显示的加上 "&" 前缀,例如getBean("&car")。

 

原文地址:https://www.cnblogs.com/yanze/p/10577217.html