【spring】beanFactory与FactoryBean的区别

1. BeanFactory

BeanFactory,以Factory结尾,表示它是一个工厂类(接口), 它负责生产和管理bean的一个工厂。

在Spring中,BeanFactory是IOC容器的核心接口,它的职责包括:实例化、定位、配置应用程序中的对象及建立这些对象间的依赖。

BeanFactory只是个接口,并不是IOC容器的具体实现,但是Spring容器给出了很多种实现,如 DefaultListableBeanFactoryXmlBeanFactoryApplicationContext等,其中XmlBeanFactory就是常用的一个,该实现将以XML方式描述组成应用的对象及对象间的依赖关系。

BeanFactory接口最重要的方法就是getBean:

public interface BeanFactory {
    
    

	Object getBean(String name) throws BeansException;

1.1 例子

Car.java,这个普通的bean,有3个属性:

必须提供get、set方法用来设置属性

package com.my.test;

public class Car {
    
    
    //最大速度,单位千米/小时
    private int maxSpeed;
    //品牌
    private String brand;
    //价格,单位元
    private double price;

    //-----提供属性的get和set方法

    public int getMaxSpeed() {
    
    
        return this.maxSpeed;
    }

    public void setMaxSpeed(int maxSpeed) {
    
    
        this.maxSpeed = maxSpeed;
    }

    public String getBrand() {
    
    
        return this.brand;
    }

    public void setBrand(String brand) {
    
    
        this.brand = brand;
    }

    public double getPrice() {
    
    
        return this.price;
    }

    public void setPrice(double price) {
    
    
        this.price = price;
    }
}

main方法执行代码:

package com.my.test;

import org.springframework.context.support.ClassPathXmlApplicationContext;

public class MainTest {
    
    
    public static void main(String[] args) {
    
    

        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");

        Car car = (Car) context.getBean("car");
        System.out.println(car.getBrand()+" "+car.getMaxSpeed()+" "+car.getPrice());

    }
}

beans.xml,放在根路径,也可以放在其他位置,和main方法中保持一致即可:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">


    <bean id="car" class="com.my.test.Car">
        <property name="brand" value="法拉利"/>
        <property name="maxSpeed" value="400"/>
        <property name="price" value="2000000"/>
    </bean>


</beans>

路径:
在这里插入图片描述

执行结果:

法拉利 400 2000000.0

2. FactoryBean

Spring中共有两种bean,一种为普通bean,另一种则为工厂bean,即FactoryBean。

普通bean如同前文中:

<bean id="car" class="com.my.test.Car">
        <property name="brand" value="法拉利"/>
        <property name="maxSpeed" value="400"/>
        <property name="price" value="2000000"/>
    </bean>

通过context.getBean(“car”);获取的bean时候,类型就是bean.xml中class属性定义的"com.my.test.Car"

那么工厂bean是什么呢?
简单来说,FactoryBean的作用是创建一个bean,类似工厂方法。

工厂方法可以参见《实例化Bean(使用静态工厂方法实例化、使用实例工厂方法实例化)》

以Bean结尾,表示它是一个Bean,不同于普通Bean的是:它是实现了FactoryBean<T>接口的Bean,根据该Bean的ID从BeanFactory中获取的实际上是FactoryBean的getObject()返回的对象,而不是FactoryBean本身(FactoryBean本身是指class属性定义的),如果要获取FactoryBean对象,请在id前面加一个&符号来获取。

一般情况下,Spring通过反射机制利用<bean>的class属性指定实现类实例化Bean,在某些情况下,实例化Bean过程比较复杂,如果按照传统的方式,则需要在<bean>中提供大量的配置信息。配置方式的灵活性是受限的,这时采用编码的方式可能会得到一个简单的方案。

Spring为此提供了一个org.springframework.bean.factory.FactoryBean的工厂类接口,用户可以通过实现该接口定制实例化Bean的逻辑。FactoryBean接口对于Spring框架来说占用重要的地位,Spring自身就提供了70多个FactoryBean的实现。它们隐藏了实例化一些复杂Bean的细节,给上层应用带来了便利。从Spring3.0开始,FactoryBean开始支持泛型,即接口声明改为FactoryBean<T>的形式。

2.1 例子:

我们基于<1.1 例子>改造:

CarFactoryBean.java,继承了FactoryBean接口:

需要实现getObject()和getObjectType(),getObject()返回值是Car

package com.my.test;

import org.springframework.beans.factory.FactoryBean;

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<?> getObjectType() {
    
    
        return Car.class;
    }

    public void setCarInfo(String carInfo) {
    
    
        this.carInfo = carInfo;
    }
}

修改beans.xml:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">


    <!--<bean id="car" class="com.my.test.Car">-->
        <!--<property name="brand" value="法拉利"/>-->
        <!--<property name="maxSpeed" value="400"/>-->
        <!--<property name="price" value="2000000"/>-->
    <!--</bean>-->

    <bean id="car" class="com.my.test.CarFactoryBean"  >
        <property name="carInfo" value="法拉利,400,2000000"/>
    </bean>


</beans>

执行结果,和普通bean的输出结果一致,调用getBean方法时获得的结果类型是Car:

法拉利 400 2000000.0

分析:
我们在beans.xml中定义的class="com.my.test.CarFactoryBean",并不是"…Car”,但是,当调用getBean方法时,其值却是个Car类型:

Car car = (Car) context.getBean("car");

如果希望获取CarFactoryBean自身的实例,则需要在使用getBean(beanName)方法时在beanName前显示的加上"&“前缀:如getBean(”&car");

猜你喜欢

转载自blog.csdn.net/m0_45406092/article/details/114805287