FactoryBean源码解析

/ Spring / 没有评论 / 20浏览

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的有这么几种情况:

beanInstancenamegetBean
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的解析就到此结束。