BeanFactory与FactoryBean

 

区别:BeanFactory是个Factory,也就是IOC容器或对象工厂,负责生产和管理bean, spring容器对该接口有多种实现,如:DefaultListableBeanFactory、XmlBeanFactory、ApplicationContext等,其中XmlBeanFactory就是常用的一个,该实现将以XML方式描述组成应用的对象及对象间的依赖关系。FactoryBean是个Bean。在Spring中,所有的Bean都是由BeanFactory(也就是IOC容器)来进行管理的。但对FactoryBean而言,这个Bean不是简单的Bean,而是一个能生产或者修饰对象生成的工厂Bean,它的实现与设计模式中的工厂模式和修饰器模式类似,即可以自定义实现bean的实例化过程

生成一个普通的bean类

 

/**
* @author MM
* @create 2018-08-06 15:32
**/
public class Car {

String name;


public Car() {
}

public Car(String name) {
this.name = name;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}


public void run() {
System.out.println(this.name + " is running");
}

}

如果是直接通过BeanFactory实例化只需要简单配置

<bean id= "car" class = "com.deam.entity.Car">

  <property name="name" value =  "beanFactory"></property>

</bean>

 然后通过spring容器实例化

        ApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml");
        BeanFactory factory = (BeanFactory) ctx;

        Car car1 = (Car) factory.getBean("car");
        car1.run();

日志显示:

八月 06, 2018 4:43:56 下午 org.springframework.context.support.AbstractApplicationContext prepareRefresh
信息: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@17ed40e0: startup date [Mon Aug 06 16:43:56 CST 2018]; root of context hierarchy
八月 06, 2018 4:43:56 下午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
信息: Loading XML bean definitions from class path resource [beans.xml]
beanFactory is running

Process finished with exit code 0

通过FactoryBean 实例化,创建一个bean实现FactoryBean接口重写getObject方法

/**
 * @author MM
 * @create 2018-08-06 16:29
 **/
public class CarFactoryBean implements FactoryBean<Car> {

    String carInfo;

    public String getCarInfo() {
        return carInfo;
    }

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

    @Nullable
    @Override
    public Car getObject() throws Exception {

        Car car = new Car(carInfo);

        return car;
    }

    @Nullable
    @Override
    public Class<?> getObjectType() {
        return null;
    }

    @Override
    public boolean isSingleton() {
        return false;
    }
}

配置容器实例化FactoryBean

<bean id="car" class="com.demo.util.CarFactoryBean">
<property name="carInfo" value="factoryBean"></property>
</bean>

 

        ApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml");
        BeanFactory factory = (BeanFactory) ctx;

        Car car1 = (Car) factory.getBean("car");
        car1.run();
        Car car2 = (Car) factory.getBean("car");
        System.out.println("car1==car2 is " + (car1 == car2));

        CarFactoryBean factoryBean = (CarFactoryBean) factory.getBean("&car");
        System.out.println(factoryBean.getCarInfo());

日志显示:

  

八月 06, 2018 4:48:57 下午 org.springframework.context.support.AbstractApplicationContext prepareRefresh
信息: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@17ed40e0: startup date [Mon Aug 06 16:48:57 CST 2018]; root of context hierarchy
八月 06, 2018 4:48:57 下午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
信息: Loading XML bean definitions from class path resource [beans.xml]
factoryBean is running
car1==car2 is false
factoryBean

 

 

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

 

 

1、FactoryBean与factory-bean的作用都是通过其他的一个bean工厂产生一个真实的bean,不同的是,FactoryBean是使用了spring默认的接口,具有一定侵入性,对框架造成依赖,factory-bean不会改变代码接口,属于注入方式。spring中很多类似的组队,比如init-method和InitializingBean。

2、从原则上,我们使用spring,很大的优点在于它没有侵略性。那么为什么会提供接口形式呢。接口形式更倾向于框架的使用,比如spirng的另一个重要的特性AOP,框架编写了AOPFactoryBean,我们不需要知道他内部实现,也不会获取他的实力,只需要配置它需要代理的类和接口,便可以成功返回一个真实的bean,也就是目标类的代理类,从而完成各种工作。

3、可以说spirng的很多扩展工作都是基于预留接口提供,同时新扩展的功能也会提供新的预留接口,比如aop的切面等。

posted @ 2018-08-27 22:04  小阿Q的博客  阅读(393)  评论(0编辑  收藏  举报