BeanFactory和FactoryBean区别(含源码分析)

2018-12-19  本文已影响0人  冷冷DerFan

1.BeanFactory

BeanFactory是Spring中的一个接口,是一个工厂类,用于管理Bean。BeanFactory是IOC容器的核心,指责包括:实例化,配置应用程序中的对象和建立这些对象之间的依赖关系,ApplicationContext则是BeanFactory的高级版本。

XMLBeanFactory是BeanFactory的一种实现,通过读取XML元数据中的信息,来实例化Bean,交由Spring容器管理,构建一个可配置的应用。

BeaFactory中有如下方法:

boolean containsBean(String beanName)

Object getBean(String)

Object getBean(String, Class)

Class getType(String name)

boolean isSingleton(String)

String[] getAliases(String name)

可以方便地获取bean,对Bean进行操作和判断。

2.FactoryBean则是一种可以定制实例化Bean的方式,通过实现FactoryBean,完成自定义的Bean实例化细节。例如可以通过FactoryBean代理对象,对其所有方法进行拦截,形成AOP类似功能。使用FactoryBean避免了在XML文件中配置各种属性,更灵活,但是需要在FactoryBean的实现类中编码完成类的实例化方式。

FactoryBean有如下方法:

public interface FactoryBean<T> {

   T getObject() throws Exception;

   Class<?> getObjectType();

   boolean isSingleton();

}

支持泛型,可将被实际对象传入,调用getObject方法时返回的是传入泛型的指定对象类型。

先用一个例子使用一下FactoryBean:

@Component("carFactoryBean")
public class CarFactoryBean implements FactoryBean<Car> {

    private String carInfo;

    public String getCarInfo() {
        return carInfo;
    }

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

    @Override
    public Car getObject() throws Exception {
        Car car = new Car();
        car.setBrand(carInfo.split(",")[0]);
        car.setName(carInfo.split(",")[1]);
        return car;
    }

    @Override
    public Class<?> getObjectType() {
        return Car.class;
    }

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

    public static void main(String[] args) {

    }
}

XML文件配置如下

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="carFactoryBean" class="com.fanfte.spring.CarFactoryBean" >
        <property name="carInfo" value="BMW,AAA"></property>
    </bean>

</beans>

在客户端中使用:

public class Main {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("application-test.xml");
        Car o1 = context.getBean("carFactoryBean", Car.class);
        Object o2 = context.getBean("&carFactoryBean");
        System.out.println(o1.getClass() + " " + o1.getName());
        System.out.println(o2.getClass());
    }
}

实际输出

class com.fanfte.spring.Car AAA
class com.fanfte.spring.CarFactoryBean

如果getBean传入参数位bean的名称,加上"&"则会返回FactoryBean对象本身。

接下来查看一下源码看看Spring中context.getBean("carFactoryBean", Car.class);做了什么

跟踪doGetBean可以到如下方法

protected <T> T doGetBean(
      final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)
      throws BeansException {

   final String beanName = transformedBeanName(name);
   Object bean;

   // 在此获取到了carFactoryBean实例
   Object sharedInstance = getSingleton(beanName);
   if (sharedInstance != null && args == null) {
      if (logger.isDebugEnabled()) {
         if (isSingletonCurrentlyInCreation(beanName)) {
            logger.debug("Returning eagerly cached instance of singleton bean '" + beanName +
                  "' that is not fully initialized yet - a consequence of a circular reference");
         }
         else {
            logger.debug("Returning cached instance of singleton bean '" + beanName + "'");
         }
      }
      // 此处获取到FactoryBean中的对象
      bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
   }

在getObjectForBeanInstance中判断是否是FactoryBean对象,如果是,则通过它的getObject()获取对象方法构造对象。

protected Object getObjectForBeanInstance(
      Object beanInstance, String name, String beanName, RootBeanDefinition mbd) {

   // 验证是否是FactoryBean对象,不是则抛出异常
   // 1.bean的name如果以&开头,则是FactoryBean实例,判断是否是FactoryBean的实例
   // 2.是否是FactoryBean的实例
   // 如果以&开头,但不是FactoryBean实例,则抛出异常
   if (BeanFactoryUtils.isFactoryDereference(name) && !(beanInstance instanceof FactoryBean)) {
      throw new BeanIsNotAFactoryException(transformedBeanName(name), beanInstance.getClass());
   }

   // 执行到此处,已经得到了bean,如果是普通的bean,或者是FacoryBean实例,直接返回
   // 是factoryBean实例,BeanFactoryUtils.isFactoryDereference则是以是否以&开头判断的
   if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) {
      return beanInstance;
   }
   // 如果不是以&开头的FactoryBean,从FactoryBeanObjectCache中获取由Factory创建的bean
   Object object = null;
   if (mbd == null) {
      // 从FactoryBeanObjectCache中获取由Factory创建的bean
      object = getCachedObjectForFactoryBean(beanName);
   }
   // 没有在cache中获取到bean
   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的工作委托给getObjectFormFactoryBean方法
      object = getObjectFromFactoryBean(factory, beanName, !synthetic);
   }
   return object;
}

String FACTORY_BEAN_PREFIX = "&";
// 判断bean的name是否是factoryBean,判断是否以&开头
public static boolean isFactoryDereference(String name) {
   return (name != null && name.startsWith(BeanFactory.FACTORY_BEAN_PREFIX));
}

进入getObjectFromFactoryBean方法

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) {
            // 实际获取FactoryBean
            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 (object != null && shouldPostProcess) {
                  try {
                     object = postProcessObjectFromFactoryBean(object, beanName);
                  }
                  catch (Throwable ex) {
                     throw new BeanCreationException(beanName,
                           "Post-processing of FactoryBean's singleton object failed", ex);
                  }
               }
               this.factoryBeanObjectCache.put(beanName, (object != null ? object : NULL_OBJECT));
            }
         }
         return (object != NULL_OBJECT ? object : null);
      }
   }
   else {
      Object object = doGetObjectFromFactoryBean(factory, beanName);
      if (object != null && shouldPostProcess) {
         try {
            object = postProcessObjectFromFactoryBean(object, beanName);
         }
         catch (Throwable ex) {
            throw new BeanCreationException(beanName, "Post-processing of FactoryBean's object failed", ex);
         }
      }
      return object;
   }
}

进入获取FactoryBean中对象的方法

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(new PrivilegedExceptionAction<Object>() {
               @Override
               public Object run() throws Exception {
                     return factory.getObject();
                  }
               }, acc);
         }
         catch (PrivilegedActionException pae) {
            throw pae.getException();
         }
      }
      else {
         // 调用carFactoryBean的getObject()方法,进行自定义实例化bean
         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 && isSingletonCurrentlyInCreation(beanName)) {
      throw new BeanCurrentlyInCreationException(
            beanName, "FactoryBean which is currently in creation returned null from getObject");
   }
   return object;
}

最后进入carFactoryBean的getObject()方法。

@Override
public Car getObject() throws Exception {
    Car car = new Car();
    car.setBrand(carInfo.split(",")[0]);
    car.setName(carInfo.split(",")[1]);
    return car;
}

至此,自定义通过factoryBean获取对象完成。

总结:

1.BeanFactory是Spring的工厂接口,为IOC容器的核心实现。FactoryBean提供了方法自定义实现Bean,避免了复杂的配置,可用于实现对象代理等,封装了对象创建的内部实现,并提供了获取对象的接口。

上一篇下一篇

猜你喜欢

热点阅读