美文网首页
BeanFactory和FactoryBean区别(含源码分析)

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

作者: 冷冷DerFan | 来源:发表于2018-12-19 18:24 被阅读0次

    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,避免了复杂的配置,可用于实现对象代理等,封装了对象创建的内部实现,并提供了获取对象的接口。

    相关文章

      网友评论

          本文标题:BeanFactory和FactoryBean区别(含源码分析)

          本文链接:https://www.haomeiwen.com/subject/ypfskqtx.html