1、FactoryBean和BeanFactory的区别
BeanFactory,就是bean的工厂,主要是通过定位、加载、注册以及实例化来维护对象与对象之间的依赖关系,以此来管理bean
FactoryBean,bean的一种,顾名思义,它也可以用来生产bean,也实现了相应的工厂方法。
一般来说,Bean是由BeanFactory生产,但FactoryBean的特殊之处就在于它也能生产bean。
获取FactoryBean的方法是getBean("&"+beanName);
就是在beanName加个"&"前缀,若直接getBean(beanName),获取到的是FactoryBean通过getObject接口生成的Bean。见代码:
Car
public class Car {
private int maxSpeed;
private String brand;
private double price;
public int getMaxSpeed() {
return maxSpeed;
}
public void setMaxSpeed(int maxSpeed) {
this.maxSpeed = maxSpeed;
}
public String getBrand() {
return brand;
}
public void setBrand(String brand) {
this.brand = brand;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
}
CarFactoryBean:
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;
}
@Override
public boolean isSingleton() {
return false;
}
public String getCarInfo() {
return carInfo;
}
public void setCarInfo(String carInfo) {
this.carInfo = carInfo;
}
}
bean配置:
<bean id="car" class="com.wl.service.factorybean.CarFactoryBean" >
<property name="carInfo" value="超级跑车,200,20000000"/>
</bean>
测试:
ApplicationContext context = new ClassPathXmlApplicationContext("classpath*:applicationContext.xml");
Object car = context.getBean("car");
Object carFactoryBean = context.getBean("&car");
System.out.println(car);
System.out.println(carFactoryBean);
结果为:
com.wl.service.factorybean.Car@13805618
com.wl.service.factorybean.CarFactoryBean@56ef9176
经过上面的测试可以知道,通过“&”前缀可以获取到FactoryBean,不加前缀获取到的则是普通的bean。
2、factoryBean的源码走读
public interface FactoryBean<T> {
@Nullable
T getObject() throws Exception;
@Nullable
Class<?> getObjectType();
default boolean isSingleton() {
return true;
}
}
实现该接口的类需要实现以上的方法,其中getObject就是用来生产bean的方法。
通过AbstractBeanFactory.doGetBean可以知道,不论是单例还是原型的实例对象,最终都要通过getObjectForBeanInstance进行转换,最终得到的才是符合要求的bean实例。如:
// Create bean instance.
//单例的处理
//首先创建beanFactory,即ObjectBeanFacotry并实现getObject接口
if (mbd.isSingleton()) {
sharedInstance = getSingleton(beanName, () -> {
try {
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
// Explicitly remove instance from singleton cache: It might have been put there
// eagerly by the creation process, to allow for circular reference resolution.
// Also remove any beans that received a temporary reference to the bean.
destroySingleton(beanName);
throw ex;
}
});
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
进入到getObjectForBeanInstance
protected Object getObjectForBeanInstance(
Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {
//进行类型检测,如果是&作为前缀,但是传入beanInstance不是FactoryBean类型的,则抛出异常
if (BeanFactoryUtils.isFactoryDereference(name)) {
if (beanInstance instanceof NullBean) {
return beanInstance;
}
if (!(beanInstance instanceof FactoryBean)) {
throw new BeanIsNotAFactoryException(transformedBeanName(name), beanInstance.getClass());
}
}
// Now we have the bean instance, which may be a normal bean or a FactoryBean.
// If it's a FactoryBean, we use it to create a bean instance, unless the
// caller actually wants a reference to the factory.
//如果是非FactoryBean或者是&作为前缀的前缀,则返回实例对象,无需转换
if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) {
return beanInstance;
}
//需要转换,说明输入的name获取的bean是需要调用FactoryBean的getObject
//也就是说,beanInstance是FactoryBean类型,同时name不是以&作为前缀
//举个例子:
//<bean id="car" class="com.wl.service.factorybean.CarFactoryBean" >
// <property name="carInfo" value="超级跑车,200,20000000"/>
//</bean>
//这里输入getBean("car"),首先beanInstance为CarFactoryBean,则需要通过CarFactoryBean.getObject进行转换
Object object = null;
if (mbd == null) {
//先到FactoryBean生产bean对象的缓存中去取,如果没有的话则用factorybean去生产一个
object = getCachedObjectForFactoryBean(beanName);
}
if (object == null) {
// Return bean instance from factory.
FactoryBean<?> factory = (FactoryBean<?>) beanInstance;
// Caches object obtained from FactoryBean if it is a singleton.
if (mbd == null && containsBeanDefinition(beanName)) {
mbd = getMergedLocalBeanDefinition(beanName);
}
boolean synthetic = (mbd != null && mbd.isSynthetic());
//通过factoryBean去生产bean
object = getObjectFromFactoryBean(factory, beanName, !synthetic);
}
return object;
}
通过这个方法我们可以得出以下几点:
1)getObjectForBeanInstance这个方法通过输入的beanInstance的有这么几种情况:
beanInstance | name | getBean |
---|---|---|
instance of FactoryBean为true | 非“&”前缀 | 抛出异常 |
instance of FactoryBean为false | 非“&”前缀 | 返回beanInstance |
instance of FactoryBean为true | “&”前缀 | 返回beanInstance同时也是FactoryBean |
instance of FactoryBean为true | 非“&”前缀 | 先通过getCachedObjectForFactoryBean去缓存取该对象,如果没有表示第一次获取,通过FactoryBean生成 |
3、factoryBean的源码深入走读
首先,假如现在要获取的是FactoryBean生成的bean实例,那么首先,会去缓存中取这个bean
Object object = null;
if (mbd == null) {
//先到FactoryBean生产bean对象的缓存中去取,如果没有的话则用factorybean去生产一个
object = getCachedObjectForFactoryBean(beanName);
}
进入到getCachedObjectForFactoryBean,是FactoryBeanRegistrySupport的方法
/** Cache of singleton objects created by FactoryBeans: FactoryBean name --> object */
/** 由factoryBean生成的单例bean都会缓存到factoryBeanObjectCache*/
private final Map<String, Object> factoryBeanObjectCache = new ConcurrentHashMap<>(16);
protected Object getCachedObjectForFactoryBean(String beanName) {
return this.factoryBeanObjectCache.get(beanName);
}
假如获取不到,则生成对应的FactoryBean,然后通过FactoryBean去生成
if (object == null) {
//获取对应的FactoryBean
FactoryBean<?> factory = (FactoryBean<?>) beanInstance;
//......省略
//通过factoryBean去生产bean
object = getObjectFromFactoryBean(factory, beanName, !synthetic);
}
进入到getObjectFromFactoryBean,是FactoryBeanRegistrySupport的方法
protected Object getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess) {
//针对单例的处理
if (factory.isSingleton() && containsSingleton(beanName)) {
synchronized (getSingletonMutex()) {
Object object = this.factoryBeanObjectCache.get(beanName);
if (object == null) {
//通过factory.getObject获取
object = doGetObjectFromFactoryBean(factory, beanName);
// Only post-process and store if not put there already during getObject() call above
// (e.g. because of circular reference processing triggered by custom getBean calls)
Object alreadyThere = this.factoryBeanObjectCache.get(beanName);
if (alreadyThere != null) {
object = alreadyThere;
}
else {
if (shouldPostProcess) {
if (isSingletonCurrentlyInCreation(beanName)) {
// Temporarily return non-post-processed object, not storing it yet..
return object;
}
beforeSingletonCreation(beanName);
try {
object = postProcessObjectFromFactoryBean(object, beanName);
}
catch (Throwable ex) {
throw new BeanCreationException(beanName,
"Post-processing of FactoryBean's singleton object failed", ex);
}
finally {
afterSingletonCreation(beanName);
}
}
if (containsSingleton(beanName)) {
//将获取到的对象放到factoryBeanObjectCache单例缓存map进行存储
this.factoryBeanObjectCache.put(beanName, object);
}
}
}
return object;
}
}
else {
//非单例的处理,直接通过factory.getObejct获取,然后再返回给用户
Object object = doGetObjectFromFactoryBean(factory, beanName);
if (shouldPostProcess) {
try {
object = postProcessObjectFromFactoryBean(object, beanName);
}
catch (Throwable ex) {
throw new BeanCreationException(beanName, "Post-processing of FactoryBean's object failed", ex);
}
}
return object;
}
}
无论是单例和非单例,都会调用doGetObjectFromFactoryBean方法,看来此方法,就是生成bean对象的方法:
private Object doGetObjectFromFactoryBean(final FactoryBean<?> factory, final String beanName)
throws BeanCreationException {
Object object;
try {
if (System.getSecurityManager() != null) {
AccessControlContext acc = getAccessControlContext();
try {
object = AccessController.doPrivileged((PrivilegedExceptionAction<Object>) factory::getObject, acc);
}
catch (PrivilegedActionException pae) {
throw pae.getException();
}
}
else {
object = factory.getObject();//生成对象
}
}
catch (FactoryBeanNotInitializedException ex) {
throw new BeanCurrentlyInCreationException(beanName, ex.toString());
}
catch (Throwable ex) {
throw new BeanCreationException(beanName, "FactoryBean threw exception on object creation", ex);
}
// Do not accept a null value for a FactoryBean that's not fully
// initialized yet: Many FactoryBeans just return null then.
if (object == null) {
if (isSingletonCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(
beanName, "FactoryBean which is currently in creation returned null from getObject");
}
object = new NullBean();
}
return object;
}
至此,针对FactoryBean的解析就到此结束。