首先,BeanFactory
,FactoryBean
都是Spring
中的接口。
-
BeanFactory
顾名思义,是用来管理,配置Bean
的Factory
。 -
FactoryBean
顾名思义,首先是一个Bean
,为什么叫FactoryBean
,因为它是由Spring
管理的,一个产生Bean
的Bean
,调用它真正返回的Bean
不是factoryBean
的实例,而是返回实现该接口的getObject()
中返回的Bean
,如果要返回该FactoryBean
实例,需要在调用的位置加上&
号。
首先看一下接口:
public interface FactoryBean<T> {
//通过Spring容器获取的Bean实质是getObject()方法返回的对象T
T getObject() throws Exception;
//返回类型
Class<?> getObjectType();
//是否单例
boolean isSingleton();
}
举个例子:
- 首先定义一个Bean:
package com.github.jettyrun.springinterface.demo.bean;
/**
* Created by jetty on 18/1/31.
*/
public class Car {
private String name;
private String color;
private String weight;
public void setName(String name) {
this.name = name;
}
public void setColor(String color) {
this.color = color;
}
public void setWeight(String weight) {
this.weight = weight;
}
}
- 实现两种不同的FactoryBean,一种单例(Singleton),一种多例(protoType)
package com.github.jettyrun.springinterface.demo.factorybean;
import com.github.jettyrun.springinterface.demo.bean.Car;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.stereotype.Component;
/**
* Created by jetty on 18/1/31.
*/
@Component("protoTypeCarFactoryBean")
public class ProtoTypeCarFactoryBean implements FactoryBean<Car>{
public Car getObject() throws Exception {
return new Car();
}
public Class<?> getObjectType() {
return Car.class;
}
public boolean isSingleton() {
return false;
}
}
package com.github.jettyrun.springinterface.demo.factorybean;
import com.github.jettyrun.springinterface.demo.bean.Car;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.stereotype.Component;
/**
* Created by jetty on 18/1/31.
*/
@Component("singletonCarFactoryBean")
public class SingletonCarFactoryBean implements FactoryBean<Car>{
private Car carProxy=new Car();
public Car getObject() throws Exception {
return carProxy;
}
public Class<?> getObjectType() {
return null;
}
public boolean isSingleton() {
return true;
}
}
- main方法运行测试
package com.github.jettyrun.springinterface.demo.factorybean;
import com.github.jettyrun.springinterface.demo.bean.Car;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* Created by jetty on 18/1/31.
*/
public class Main {
public static void main(String[] args) {
ApplicationContext beans=new ClassPathXmlApplicationContext("classpath:application-usertag.xml");
Car protoTypeCar1= (Car)beans.getBean("protoTypeCarFactoryBean");
Car protoTypeCar2= (Car)beans.getBean("protoTypeCarFactoryBean");
System.out.println(""+(protoTypeCar1==protoTypeCar2)+" "+protoTypeCar1+" "+protoTypeCar2);
Car singletonCar1= (Car)beans.getBean("singletonCarFactoryBean");
Car singletonCar2= (Car)beans.getBean("singletonCarFactoryBean");
System.out.println(""+(singletonCar1==singletonCar2)+" "+singletonCar1+" "+singletonCar2);
SingletonCarFactoryBean factoryBean1=(SingletonCarFactoryBean)beans.getBean("&singletonCarFactoryBean");
SingletonCarFactoryBean factoryBean2=(SingletonCarFactoryBean)beans.getBean("&singletonCarFactoryBean");
System.out.println(""+(factoryBean1==factoryBean2)+" "+factoryBean1+" "+factoryBean2);
}
}
- 运行结果:
false com.github.jettyrun.springinterface.demo.bean.Car@710f4d59 com.github.jettyrun.springinterface.demo.bean.Car@239f480c
true com.github.jettyrun.springinterface.demo.bean.Car@2e331e19 com.github.jettyrun.springinterface.demo.bean.Car@2e331e19
true com.github.jettyrun.springinterface.demo.factorybean.SingletonCarFactoryBean@1dfd1301 com.github.jettyrun.springinterface.demo.factorybean.SingletonCarFactoryBean@1dfd1301
我们能看到,通过Spring容器获取protoTypeCarFactoryBean
,singletonCarFactoryBean
对象,实质返回的是该对象调用的getObject()
方法返回的对象,如果要获取FactoryBean
的真正类型,则需要在beanId
前加上&
符号。
BeanFactory到底又是如何使用的。
我们将上面的main方法做一下改变,将ApplicationContext改为BeanFactory。如下:
public static void main(String[] args){
Resource resource = new FileSystemResource("src/main/resources/application-usertag.xml");
BeanFactory factory = new XmlBeanFactory(resource);
Car protoTypeCar1= (Car)factory.getBean("protoTypeCarFactoryBean");
Car protoTypeCar2= (Car)factory.getBean("protoTypeCarFactoryBean");
System.out.println(""+(protoTypeCar1==protoTypeCar2)+" "+protoTypeCar1+" "+protoTypeCar2);
Car singletonCar1= (Car)factory.getBean("singletonCarFactoryBean");
Car singletonCar2= (Car)factory.getBean("singletonCarFactoryBean");
System.out.println(""+(singletonCar1==singletonCar2)+" "+singletonCar1+" "+singletonCar2);
SingletonCarFactoryBean factoryBean1=(SingletonCarFactoryBean)factory.getBean("&singletonCarFactoryBean");
SingletonCarFactoryBean factoryBean2=(SingletonCarFactoryBean)factory.getBean("&singletonCarFactoryBean");
System.out.println(""+(factoryBean1==factoryBean2)+" "+factoryBean1+" "+factoryBean2);
}
运行结果和上面的运行结果完全一样。
这就表示着在Spring中,所有的bean
都是被beanFactory
管理,需要获取bean的时候,实质是去beanFactory
中获取。applicationContext
本身是实现BeanFactory
接口的实现。
如下:
public interface ApplicationContext extends EnvironmentCapable, ListableBeanFactory, HierarchicalBeanFactory,
MessageSource, ApplicationEventPublisher, ResourcePatternResolver {
HierarchicalBeanFactory
本身是继承BeanFactory
接口的。
也就是上面所说的,FactoryBean
是一个为了产生Bean
的 Bean
,而BeanFactory
是用来管理,产生Bean
的一个Factory
。
代码地址:https://gitee.com/shxz130/SpringInterfaceDemo/