Hadoop Common源码分析之SerializationFactory、Serialization

        SerializationFactory是Hadoop中的一个序列化器工厂,它除了用来存储序列化器种类、更新序列化器相关配置信息,还提供了根据指定待序列化类获取相匹配的序列化器和反序列化器的功能。

        SerializationFactory中的关键成员变量只有一个,如下:

private List<Serialization<?>> serializations = new ArrayList<Serialization<?>>();
        serializations是一个存储实现Serialization接口对象的列表,而Serialization代表了序列化器或反序列化器的公共行为,它实际上是对序列化器/反序列化器对的压缩,列表中的对象其实是(序列化器/反序列化器对)的结合体,提供了以下三个方法:

/**
 * <p>
 * Encapsulates a {@link Serializer}/{@link Deserializer} pair.
 * </p>
 * @param <T>
 */
@InterfaceAudience.LimitedPrivate({"HDFS", "MapReduce"})
@InterfaceStability.Evolving
public interface Serialization<T> {
  
  /**
   * Allows clients to test whether this {@link Serialization}
   * supports the given class.
   * 允许客户端去检测这个Serialization是否支持给定Class
   */
  boolean accept(Class<?> c);
  
  /**
   * 为给定Class获取一个序列化器Serializer
   * @return a {@link Serializer} for the given class.
   */
  Serializer<T> getSerializer(Class<T> c);

  /**
   * 为给定Class获取一个反序列化器Deserializer
   * @return a {@link Deserializer} for the given class.
   */
  Deserializer<T> getDeserializer(Class<T> c);
}
        很明显,accept(Class<?> c)方法允许客户端去检测这个Serialization是否支持给定Class,getSerializer(Class<T> c)方法为给定Class获取一个序列化器Serializer,而getDeserializer(Class<T> c)方法为给定Class获取一个反序列化器Deserializer。

        我们再看SerializationFactory的构造函数,它通过读取配置信息conf中的io.serializations参数来确定Serializations,这个参数是一个逗号隔开的类名列表,代码如下:

  /**
   * <p>
   * Serializations are found by reading the <code>io.serializations</code>
   * property from <code>conf</code>, which is a comma-delimited list of
   * classnames.
   * 通过读取配置信息conf中的io.serializations参数来确定Serializations,这个参数是一个逗号隔开的类名列表
   * </p>
   */
  public SerializationFactory(Configuration conf) {
    
	// 调用父类构造函数  
	super(conf);
    
    // 遍历参数io.serializations配置的序列器名称serializerName,
    // 参数未配置默认为WritableSerialization、AvroSpecificSerialization、AvroReflectSerialization三个
    for (String serializerName : conf.getStrings(
      CommonConfigurationKeys.IO_SERIALIZATIONS_KEY,
      new String[]{WritableSerialization.class.getName(),
        AvroSpecificSerialization.class.getName(),
        AvroReflectSerialization.class.getName()})) {
    	
      // 调用add(conf, serializerName)方法添加序列化器
      add(conf, serializerName);
    }
  }
        构造函数先调用父类构造函数,然后遍历参数io.serializations配置的序列器名称serializerName,参数未配置默认为WritableSerialization、AvroSpecificSerialization、AvroReflectSerialization三个,然后调用add(conf, serializerName)方法添加每个序列化器名称。继续追踪add()方法,代码如下:

  @SuppressWarnings("unchecked")
  private void add(Configuration conf, String serializationName) {
    try {
      // 通过类名serializationName获取Class,即serializionClass
      Class<? extends Serialization> serializionClass =
        (Class<? extends Serialization>) conf.getClassByName(serializationName);
      
      // 通过反射生成类serializionClass的对象,并将其加入到serializations列表
      serializations.add((Serialization)
      ReflectionUtils.newInstance(serializionClass, getConf()));
    } catch (ClassNotFoundException e) {
      LOG.warn("Serialization class not found: ", e);
    }
  }
        add()方法很简单,就做了两件事:

        1、通过类名serializationName获取Class,即serializionClass;

        2、通过反射生成类serializionClass的对象,这个对象其实是(序列化器/反序列化器对)的结合体,并将其加入到serializations列表。

        SerializationFactory还提供了为指定类获取序列化器、反序列化器的getSerializer(Class<T> c)和getDeserializer(Class<T> c)方法,代码如下:

  // 为指定类c获取序列化器Serializer
  public <T> Serializer<T> getSerializer(Class<T> c) {
	// 根据指定类c,调用getSerialization()方法,获取对应序列化器serializer,实际上是确定(序列化器/反序列化器对)对象serializer
    Serialization<T> serializer = getSerialization(c);
    if (serializer != null) {
      // 通过serializer的getSerializer()方法为指定类c获取序列化器的实例
      return serializer.getSerializer(c);
    }
    // 找不到则返回null
    return null;
  }

  // 为指定类c获取反序列化器Deserializer
  public <T> Deserializer<T> getDeserializer(Class<T> c) {
	// 根据指定类c,调用getSerialization()方法,获取对应序列化器serializer,实际上是确定(序列化器/反序列化器对)对象serializer
    Serialization<T> serializer = getSerialization(c);
    if (serializer != null) {
      // 通过serializer的getSerializer()方法为指定类c获取反序列化器的实例
      return serializer.getDeserializer(c);
    }
    // 找不到则返回null
    return null;
  }

  // 为指定类c获取(序列化器/反序列化器对)对象
  @SuppressWarnings("unchecked")
  public <T> Serialization<T> getSerialization(Class<T> c) {
	// 遍历serializations列表,获取其中每个Serialization对象serialization
    for (Serialization serialization : serializations) {
    	
      // 调用serialization的accept()方法,如果其与c相匹配,则返回该serialization
      if (serialization.accept(c)) {
        return (Serialization<T>) serialization;
      }
    }
    
    // 找不到则返回null
    return null;
  }
        两个方法的处理逻辑一致,大体如下:

        1、根据指定类c,调用getSerialization()方法,获取对应序列化器serializer,实际上是确定(序列化器/反序列化器对)对象serializer;

        2、通过serializer的getSerializer()方法或getDeserializer()方法为指定类c获取序列化器或发序列化器的实例,并返回;

        3、找不到则返回null。

        而两者共用的getSerialization()方法则是为指定类c获取(序列化器/反序列化器对)对象,处理逻辑大致为:遍历serializations列表,获取其中每个Serialization对象serialization,调用serialization的accept()方法,如果其与c相匹配,则返回该serialization,找不到则返回null。




        



优秀的个人博客,低调大师

微信关注我们

原文链接:https://yq.aliyun.com/articles/245623

转载内容版权归作者及来源网站所有!

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。

相关文章

发表评论

资源下载

更多资源
优质分享Android(本站安卓app)

优质分享Android(本站安卓app)

近一个月的开发和优化,本站点的第一个app全新上线。该app采用极致压缩,本体才4.36MB。系统里面做了大量数据访问、缓存优化。方便用户在手机上查看文章。后续会推出HarmonyOS的适配版本。

Mario,低调大师唯一一个Java游戏作品

Mario,低调大师唯一一个Java游戏作品

马里奥是站在游戏界顶峰的超人气多面角色。马里奥靠吃蘑菇成长,特征是大鼻子、头戴帽子、身穿背带裤,还留着胡子。与他的双胞胎兄弟路易基一起,长年担任任天堂的招牌角色。

Oracle Database,又名Oracle RDBMS

Oracle Database,又名Oracle RDBMS

Oracle Database,又名Oracle RDBMS,或简称Oracle。是甲骨文公司的一款关系数据库管理系统。它是在数据库领域一直处于领先地位的产品。可以说Oracle数据库系统是目前世界上流行的关系数据库管理系统,系统可移植性好、使用方便、功能强,适用于各类大、中、小、微机环境。它是一种高效率、可靠性好的、适应高吞吐量的数据库方案。

Eclipse(集成开发环境)

Eclipse(集成开发环境)

Eclipse 是一个开放源代码的、基于Java的可扩展开发平台。就其本身而言,它只是一个框架和一组服务,用于通过插件组件构建开发环境。幸运的是,Eclipse 附带了一个标准的插件集,包括Java开发工具(Java Development Kit,JDK)。