美文网首页
BeanFactory 与 FactoryBean 区别

BeanFactory 与 FactoryBean 区别

作者: 我是昵称鲁班 | 来源:发表于2018-11-15 17:08 被阅读13次

    BeanFacory

    字面理解:以Factory结尾,是一个工厂接口,用于管理bean工厂。

    作用
    1)实例化 (Instance)
    2)定位 (缓存Map beanId->Instance)
    3)建立bean之间的依赖关系

    Resource resource = new FileSystemResource("spring.xml");
    BeanFactory beanFactory = new XmlBeanFactory(resource);
    
    ClassPathResource resource = new ClassPathResource ("spring.xml");
    BeanFactory beanFactory(resource);
    
    Application context = new ClassPathXmlApplicationContext(new String[]{"partOne.xml","paryTwo.xml"});
    BeanFactory beanFactory =context;
    

    如果是采用微服务框架,获取ApplicaitonContext的方式可以采用下面这种:

    public ApplicationContextHelper implements  ApplicationContextAware{
    @Override
    
    }
    

    拿到beanFactory,接着使用getBean(String beanName)方法就可以取得bean的实例;

    BeanFactory方法
    1 boolean containsBean(String beanName)
    判断工厂中是否包含给定名称的bean定义,若有则返回true
    2 Object getBean(String)
    返回给定名称注册的bean实例。根据bean的配置情况,如果是singleton模式将返回一个共享实例,否则将返回一个新建的实例,如果没有找到指定bean,该方法可能会抛出异常。
    3 Object getBean(String, Class) 返回以给定名称注册的bean实例,并转换为给定class类型。
    4 Class getType(String name) 返回给定名称的bean的Class,如果没有找到指定的bean实例,则排除NoSuchBeanDefinitionException异常。
    5 boolean isSingleton(String) 判断给定名称的bean定义是否为单例模式。
    6 String[] getAliases(String name) 返回给定bean名称的所有别名。

    FactoryBean

    字面意思:以Bean为结尾,是一个Bean。不同于普通Bean该bean可以生产Bean。

    作用:通过编码的方式配置bean,可以避免复杂的配置。

    • 传统采用xml配置一个bean的方式,Spring采用反射机制根据<bean>标签中class属性指定实现一个类的实例化并装配成bean。在属性特别多的时候需要编写大量的配置信息,这种场景下配置方式的灵活性受限。

    • 编码方式注册bean能解决上述问题。Spring提供了org.springframwork.bean.factory.FactoryBean接口,用户可以通过该接口定制实例化Bean的逻辑。Spring框架自身就提供了70+FactoryBean的实现。它们隐藏了实例化一些复杂Bean的细节,给上层应用带来了便利。

    接口定义:

    public interface FactoryBean<T> {
    
       @Nullable
       T getObject() throws Exception;//返回由FactoryBean创建的bean实例,如果isSingleton()返回true,则该实例会放到Spring容器中单实例缓存池中。
    
       @Nullable
       Class<?> getObjectType();//返回FactoryBean创建的bean类型。
    
       default boolean isSingleton() {
           return true;
       }//返回由FactoryBean创建的bean实例的作用域是singleton还是prototype。
    }
    

    具体实例:

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

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

    如果用FactoryBean的方式实现就会灵活一些,下例通过逗号分割符的方式一次性地为Car的所有属性指定配置值:

    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;    
        }    
    }     
    

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

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

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

    相关文章

      网友评论

          本文标题:BeanFactory 与 FactoryBean 区别

          本文链接:https://www.haomeiwen.com/subject/bfayfqtx.html