FactoryBean源码解析

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 {

    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配置:


    

测试:

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 {  
   @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不是以&作为前缀
    //举个例子:
    //
    //  
    //
    //这里输入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 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) 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的解析就到此结束。

你可能感兴趣的:(FactoryBean源码解析)