1. 程式人生 > >fastjson深度原始碼解析- 序列化(四)

fastjson深度原始碼解析- 序列化(四)

概要

fastjson序列化主要使用入口就是在JSON.java類中,它提供非常簡便和友好的api將java物件轉換成json字串。

JSON成員函式

    /**
     *  便捷序列化java物件,序列化物件可以包含任意泛型屬性欄位,但是不適用本身是泛型的物件。
     *  預設序列化返回字串,可以使用writeJSONString(Writer, Object, SerializerFeature[])
     *  將序列化字串輸出到指定輸出器中
     */
    public static String toJSONString(Object object) {
        /**
         * 直接呼叫過載方法,將指定object序列化成json字串,忽略序列化filter
         */
return toJSONString(object, emptyFilters); }

使用便捷介面toJSONString方法,可以將任意java物件序列化為json字串,內部呼叫toJSONString(Object, SerializeFilter[], SerializerFeature... ) :

    public static String toJSONString(Object object, SerializeFilter[] filters, SerializerFeature... features) {
        return
toJSONString(object, SerializeConfig.globalInstance, filters, null, DEFAULT_GENERATE_FEATURE, features); }

繼續跟蹤方法呼叫到toJSONString(Object, SerializeConfig ,SerializeFilter[], String, int, SerializerFeature... ) :

    public static String toJSONString(Object object,                   /** 序列化物件    */
                                      SerializeConfig config,          /** 全域性序列化配置 */
                                      SerializeFilter[] filters,       /** 序列化攔截器   */
                                      String dateFormat,               /** 序列化日期格式 */
                                      int
defaultFeatures, /** 預設序列化特性 */ SerializerFeature... features) { /** 自定義序列化特性 */ /** 初始化序列化writer,用features覆蓋defaultFeatures配置 */ SerializeWriter out = new SerializeWriter(null, defaultFeatures, features); try { /** * 初始化JSONSerializer,序列化型別由它委託config查詢具體 * 序列化處理器處理,序列化結果寫入out的buffer中 */ JSONSerializer serializer = new JSONSerializer(out, config); if (dateFormat != null && dateFormat.length() != 0) { serializer.setDateFormat(dateFormat); /** 呼叫out 重新配置屬性 並且開啟WriteDateUseDateFormat特性 */ serializer.config(SerializerFeature.WriteDateUseDateFormat, true); } if (filters != null) { for (SerializeFilter filter : filters) { /** 新增攔截器 */ serializer.addFilter(filter); } } /** 使用序列化例項轉換物件,查詢具體序列化例項委託給config查詢 */ serializer.write(object); return out.toString(); } finally { out.close(); } }

這個序列化方法實際並不是真正執行序列化操作,首先做序列化特性配置,然後追加序列化攔截器,開始執行序列化物件操作委託給了config物件查詢。

我們繼續進入serializer.write(object) 檢視:

    public final void write(Object object) {
        if (object == null) {
            /** 如果物件為空,直接輸出 "null" 字串 */
            out.writeNull();
            return;
        }

        Class<?> clazz = object.getClass();
        /** 根據物件的Class型別查詢具體序列化例項 */
        ObjectSerializer writer = getObjectWriter(clazz);

        try {
            /** 使用具體serializer例項處理物件 */
            writer.write(this, object, null, null, 0);
        } catch (IOException e) {
            throw new JSONException(e.getMessage(), e);
        }
    }

序列化回撥介面

ObjectSerializer序列化介面

我們發現真正序列化物件的時候是由具體ObjectSerializer例項完成,我們首先檢視一下介面定義:

    void write(JSONSerializer serializer, /** json序列化例項 */
               Object object,       /** 待序列化的物件*/
               Object fieldName,    /** 待序列化欄位*/
               Type fieldType,      /** 待序列化欄位型別 */
               int features) throws IOException;

當fastjson序列化特定的欄位時會回撥這個方法。

我們繼續跟蹤writer.write(this, object, null, null, 0) :

    public final void write(Object object) {
        if (object == null) {
            /** 如果物件為空,直接輸出 "null" 字串 */
            out.writeNull();
            return;
        }

        Class<?> clazz = object.getClass();
        /** 根據物件的Class型別查詢具體序列化例項 */
        ObjectSerializer writer = getObjectWriter(clazz);

        try {
            /** 使用具體serializer例項處理物件 */
            writer.write(this, object, null, null, 0);
        } catch (IOException e) {
            throw new JSONException(e.getMessage(), e);
        }
    }

我們發現在方法內部呼叫getObjectWriter(clazz)根據具體型別查詢序列化例項,方法內部只有一行呼叫 config.getObjectWriter(clazz),讓我們更進一步檢視委託實現細節com.alibaba.fastjson.serializer.SerializeConfig#getObjectWriter(java.lang.Class<?>):

    public ObjectSerializer getObjectWriter(Class<?> clazz) {
        return getObjectWriter(clazz, true);
    }

內部又呼叫com.alibaba.fastjson.serializer.SerializeConfig#getObjectWriter(java.lang.Class<?>, boolean),這個類實現相對複雜了一些,我會按照程式碼順序梳理所有序列化例項的要點 :

    private ObjectSerializer getObjectWriter(Class<?> clazz, boolean create) {
        /** 首先從內部已經註冊查詢特定class的序列化例項 */
        ObjectSerializer writer = serializers.get(clazz);

        if (writer == null) {
            try {
                final ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
                /** 使用當前執行緒類載入器 查詢 META-INF/services/AutowiredObjectSerializer.class實現類 */
                for (Object o : ServiceLoader.load(AutowiredObjectSerializer.class, classLoader)) {
                    if (!(o instanceof AutowiredObjectSerializer)) {
                        continue;
                    }

                    AutowiredObjectSerializer autowired = (AutowiredObjectSerializer) o;
                    for (Type forType : autowired.getAutowiredFor()) {
                        /** 如果存在,註冊到內部serializers快取中 */
                        put(forType, autowired);
                    }
                }
            } catch (ClassCastException ex) {
                // skip
            }

            /** 嘗試在已註冊快取找到特定class的序列化例項 */
            writer = serializers.get(clazz);
        }

        if (writer == null) {
            /** 使用載入JSON類的載入器 查詢 META-INF/services/AutowiredObjectSerializer.class實現類 */
            final ClassLoader classLoader = JSON.class.getClassLoader();
            if (classLoader != Thread.currentThread().getContextClassLoader()) {
                try {
                    for (Object o : ServiceLoader.load(AutowiredObjectSerializer.class, classLoader)) {

                        if (!(o instanceof AutowiredObjectSerializer)) {
                            continue;
                        }

                        AutowiredObjectSerializer autowired = (AutowiredObjectSerializer) o;
                        for (Type forType : autowired.getAutowiredFor()) {
                            /** 如果存在,註冊到內部serializers快取中 */
                            put(forType, autowired);
                        }
                    }
                } catch (ClassCastException ex) {
                    // skip
                }

                /** 嘗試在已註冊快取找到特定class的序列化例項 */
                writer = serializers.get(clazz);
            }
        }

        if (writer == null) {
            String className = clazz.getName();
            Class<?> superClass;

            if (Map.class.isAssignableFrom(clazz)) {
                /** 如果class實現類Map介面,使用MapSerializer序列化 */
                put(clazz, writer = MapSerializer.instance);
            } else if (List.class.isAssignableFrom(clazz)) {
                /** 如果class實現類List介面,使用ListSerializer序列化 */
                put(clazz, writer = ListSerializer.instance);
            } else if (Collection.class.isAssignableFrom(clazz)) {
                /** 如果class實現類Collection介面,使用CollectionCodec序列化 */
                put(clazz, writer = CollectionCodec.instance);
            } else if (Date.class.isAssignableFrom(clazz)) {
                /** 如果class繼承Date,使用DateCodec序列化 */
                put(clazz, writer = DateCodec.instance);
            } else if (JSONAware.class.isAssignableFrom(clazz)) {
                /** 如果class實現類JSONAware介面,使用JSONAwareSerializer序列化 */
                put(clazz, writer = JSONAwareSerializer.instance);
            } else if (JSONSerializable.class.isAssignableFrom(clazz)) {
                /** 如果class實現類JSONSerializable介面,使用JSONSerializableSerializer序列化 */
                put(clazz, writer = JSONSerializableSerializer.instance);
            } else if (JSONStreamAware.class.isAssignableFrom(clazz)) {
                /** 如果class實現類JSONStreamAware介面,使用MiscCodecr序列化 */
                put(clazz, writer = MiscCodec.instance);
            } else if (clazz.isEnum()) {
                JSONType jsonType = TypeUtils.getAnnotation(clazz, JSONType.class);
                if (jsonType != null && jsonType.serializeEnumAsJavaBean()) {
                    /** 如果是列舉型別,並且啟用特性 serializeEnumAsJavaBean
                     *  使用JavaBeanSerializer序列化(假設沒有啟用asm)
                     */
                    put(clazz, writer = createJavaBeanSerializer(clazz));
                } else {
                    /** 如果是列舉型別,沒有啟用特性 serializeEnumAsJavaBean
                     *  使用EnumSerializer序列化
                     */
                    put(clazz, writer = EnumSerializer.instance);
                }
            } else if ((superClass = clazz.getSuperclass()) != null && superClass.isEnum()) {
                JSONType jsonType = TypeUtils.getAnnotation(superClass, JSONType.class);
                if (jsonType != null && jsonType.serializeEnumAsJavaBean()) {
                    /** 如果父類是列舉型別,並且啟用特性 serializeEnumAsJavaBean
                     *  使用JavaBeanSerializer序列化(假設沒有啟用asm)
                     */
                    put(clazz, writer = createJavaBeanSerializer(clazz));
                } else {
                    /** 如果父類是列舉型別,沒有啟用特性 serializeEnumAsJavaBean
                     *  使用EnumSerializer序列化
                     */
                    put(clazz, writer = EnumSerializer.instance);
                }
            } else if (clazz.isArray()) {
                Class<?> componentType = clazz.getComponentType();
                /** 如果是陣列型別,根據陣列實際型別查詢序列化例項 */
                ObjectSerializer compObjectSerializer = getObjectWriter(componentType);
                put(clazz, writer = new ArraySerializer(componentType, compObjectSerializer));
            } else if (Throwable.class.isAssignableFrom(clazz)) {
                /** 註冊通用JavaBeanSerializer序列化處理 Throwable */
                SerializeBeanInfo beanInfo = TypeUtils.buildBeanInfo(clazz, null, propertyNamingStrategy);
                beanInfo.features |= SerializerFeature.WriteClassName.mask;
                put(clazz, writer = new JavaBeanSerializer(beanInfo));
            } else if (TimeZone.class.isAssignableFrom(clazz) || Map.Entry.class.isAssignableFrom(clazz)) {
                /** 如果class實現Map.Entry介面或者繼承類TimeZone,使用MiscCodecr序列化 */
                put(clazz, writer = MiscCodec.instance);
            } else if (Appendable.class.isAssignableFrom(clazz)) {
                /** 如果class實現Appendable介面,使用AppendableSerializer序列化 */
                put(clazz, writer = AppendableSerializer.instance);
            } else if (Charset.class.isAssignableFrom(clazz)) {
                /** 如果class繼承Charset抽象類,使用ToStringSerializer序列化 */
                put(clazz, writer = ToStringSerializer.instance);
            } else if (Enumeration.class.isAssignableFrom(clazz)) {
                /** 如果class實現Enumeration介面,使用EnumerationSerializer序列化 */
                put(clazz, writer = EnumerationSerializer.instance);
            } else if (Calendar.class.isAssignableFrom(clazz)
                    || XMLGregorianCalendar.class.isAssignableFrom(clazz)) {
                /** 如果class繼承類Calendar或者XMLGregorianCalendar,使用CalendarCodec序列化 */
                put(clazz, writer = CalendarCodec.instance);
            } else if (Clob.class.isAssignableFrom(clazz)) {
                /** 如果class實現Clob介面,使用ClobSeriliazer序列化 */
                put(clazz, writer = ClobSeriliazer.instance);
            } else if (TypeUtils.isPath(clazz)) {
                /** 如果class實現java.nio.file.Path介面,使用ToStringSerializer序列化 */
                put(clazz, writer = ToStringSerializer.instance);
            } else if (Iterator.class.isAssignableFrom(clazz)) {
                /** 如果class實現Iterator介面,使用MiscCodec序列化 */
                put(clazz, writer = MiscCodec.instance);
            } else {
                /**
                 *  如果class的name是"java.awt."開頭 並且
                 *  繼承 Point、Rectangle、Font或者Color 其中之一
                 */
                if (className.startsWith("java.awt.")
                    && AwtCodec.support(clazz)
                ) {
                    // awt
                    if (!awtError) {
                        try {
                            String[] names = new String[]{
                                    "java.awt.Color",
                                    "java.awt.Font",
                                    "java.awt.Point",
                                    "java.awt.Rectangle"
                            };
                            for (String name : names) {
                                if (name.equals(className)) {
                                    /** 如果系統支援4中型別, 使用AwtCodec 序列化 */
                                    put(Class.forName(name), writer = AwtCodec.instance);
                                    return writer;
                                }
                            }
                        } catch (Throwable e) {
                            awtError = true;
                            // skip
                        }
                    }
                }

                // jdk8
                if ((!jdk8Error) //
                    && (className.startsWith("java.time.") //
                        || className.startsWith("java.util.Optional") //
                        || className.equals("java.util.concurrent.atomic.LongAdder")
                        || className.equals("java.util.concurrent.atomic.DoubleAdder")
                    )) {
                    try {
                        {
                            String[] names = new String[]{
                                    "java.time.LocalDateTime",
                                    "java.time.LocalDate",
                                    "java.time.LocalTime",
                                    "java.time.ZonedDateTime",
                                    "java.time.OffsetDateTime",
                                    "java.time.OffsetTime",
                                    "java.time.ZoneOffset",
                                    "java.time.ZoneRegion",
                                    "java.time.Period",
                                    "java.time.Duration",
                                    "java.time.Instant"
                            };
                            for (String name : names) {
                                if (name.equals(className)) {
                                    /** 如果系統支援JDK8中日期型別, 使用Jdk8DateCodec 序列化 */
                                    put(Class.forName(name), writer = Jdk8DateCodec.instance);
                                    return writer;
                                }
                            }
                        }
                        {
                            String[] names = new String[]{
                                    "java.util.Optional",
                                    "java.util.OptionalDouble",
                                    "java.util.OptionalInt",
                                    "java.util.OptionalLong"
                            };
                            for (String name : names) {
                                if (name.equals(className)) {
                                    /** 如果系統支援JDK8中可選型別, 使用OptionalCodec 序列化 */
                                    put(Class.forName(name), writer = OptionalCodec.instance);
                                    return writer;
                                }
                            }
                        }
                        {
                            String[] names = new String[]{
                                    "java.util.concurrent.atomic.LongAdder",
                                    "java.util.concurrent.atomic.DoubleAdder"
                            };
                            for (String name : names) {
                                if (name.equals(className)) {
                                    /** 如果系統支援JDK8中原子型別, 使用AdderSerializer 序列化 */
                                    put(Class.forName(name), writer = AdderSerializer.instance);
                                    return writer;
                                }
                            }
                        }
                    } catch (Throwable e) {
                        // skip
                        jdk8Error = true;
                    }
                }

                if ((!oracleJdbcError) //
                    && className.startsWith("oracle.sql.")) {
                    try {
                        String[] names = new String[] {
                                "oracle.sql.DATE",
                                "oracle.sql.TIMESTAMP"
                        };

                        for (String name : names) {
                            if (name.equals(className)) {
                                /** 如果系統支援oralcle驅動中日期型別, 使用DateCodec 序列化 */
                                put(Class.forName(name), writer = DateCodec.instance);
                                return writer;
                            }
                        }
                    } catch (Throwable e) {
                        // skip
                        oracleJdbcError = true;
                    }
                }

                if ((!springfoxError) //
                    && className.equals("springfox.documentation.spring.web.json.Json")) {
                    try {
                        /** 如果系統支援springfox-spring-web框架中Json型別, 使用SwaggerJsonSerializer 序列化 */
                        put(Class.forName("springfox.documentation.spring.web.json.Json"),
                                writer = SwaggerJsonSerializer.instance);
                        return writer;
                    } catch (ClassNotFoundException e) {
                        // skip
                        springfoxError = true;
                    }
                }

                if ((!guavaError) //
                        && className.startsWith("com.google.common.collect.")) {
                    try {
                        String[] names = new String[] {
                                "com.google.common.collect.HashMultimap",
                                "com.google.common.collect.LinkedListMultimap",
                                "com.google.common.collect.ArrayListMultimap",
                                "com.google.common.collect.TreeMultimap"
                        };

                        for (String name : names) {
                            if (name.equals(className)) {
                                /** 如果系統支援guava框架中日期型別, 使用GuavaCodec 序列化 */
                                put(Class.forName(name), writer = GuavaCodec.instance);
                                return writer;
                            }
                        }
                    } catch (ClassNotFoundException e) {
                        // skip
                        guavaError = true;
                    }
                }

                if ((!jsonnullError) && className.equals("net.sf.json.JSONNull")) {
                    try {
                        /** 如果系統支援json-lib框架中JSONNull型別, 使用MiscCodec 序列化 */
                        put(Class.forName("net.sf.json.JSONNull"), writer = MiscCodec.instance);
                        return writer;
                    } catch (ClassNotFoundException e) {
                        // skip
                        jsonnullError = true;
                    }
                }

                Class[] interfaces = clazz.getInterfaces();
                /** 如果class只實現唯一介面,並且介面包含註解,使用AnnotationSerializer 序列化 */
                if (interfaces.length == 1 && interfaces[0].isAnnotation()) {
                    return AnnotationSerializer.instance;
                }

                /** 如果使用了cglib或者javassist動態代理 */
                if (TypeUtils.isProxy(clazz)) {
                    Class<?> superClazz = clazz.getSuperclass();

                    /** 通過父型別查詢序列化,父類是真實的型別 */
                    ObjectSerializer superWriter = getObjectWriter(superClazz);
                    put(clazz, superWriter);
                    return superWriter;
                }

                /** 如果使用了jdk動態代理 */
                if (Proxy.isProxyClass(clazz)) {
                    Class handlerClass = null;

                    if (interfaces.length == 2) {
                        handlerClass = interfaces[1];
                    } else {
                        for (Class proxiedInterface : interfaces) {
                            if (proxiedInterface.getName().startsWith("org.springframework.aop.")) {
                                continue;
                            }
                            if (handlerClass != null) {
                                handlerClass = null; // multi-matched
                                break;
                            }
                            handlerClass = proxiedInterface;
                        }
                    }

                    if (handlerClass != null) {
                        /** 根據class實現介面型別查詢序列化 */
                        ObjectSerializer superWriter = getObjectWriter(handlerClass);
                        put(clazz, superWriter);
                        return superWriter;
                    }
                }

                if (create) {
                    /** 沒有精確匹配,使用通用JavaBeanSerializer 序列化(假設不啟用asm) */
                    writer = createJavaBeanSerializer(clazz);
                    put(clazz, writer);
                }
            }

            if (writer == null) {
                /** 嘗試在已註冊快取找到特定class的序列化例項 */
                writer = serializers.get(clazz);
            }
        }
        return writer;
    }

查詢具體序列化例項,查詢方法基本思想根據class型別或者實現介面型別進行匹配查詢。接下來針對逐個序列化實現依次分析。

相關推薦

fastjson深度原始碼解析- 序列()

概要 fastjson序列化主要使用入口就是在JSON.java類中,它提供非常簡便和友好的api將java物件轉換成json字串。 JSON成員函式 /** * 便捷序列化java物件,序列化物件可以包含任意泛型屬性欄位,但是

fastjson深度原始碼解析- 序列(五)

序列化回撥介面實現分析 內部註冊的序列化 fastjson針對常用的型別已經註冊了序列化實現方案: 註冊的型別 序列化例項 是否支援序列化 是否支援反序列化 Boolean BooleanCodec 是 是

fastjson深度原始碼解析- 反序列(二)

反序列化回撥介面實現分析 內部註冊的反序列化 fastjson針對常用的型別已經註冊了反序列化實現方案,根據原始碼註冊com.alibaba.fastjson.parser.ParserConfig#initDeserializers可以得到列表:

fastjson深度原始碼解析- 詞法和語法解析(二)

JSON Token解析 JSONLexerBase定義並實現了json串實現解析機制的基礎,在理解後面反序列化之前,我們先來看看並理解重要的屬性: /** 當前token含義 */ protected int

記錄一次原始碼擴充套件案列——FastJson自定義反序列ValueMutator

背景:曾經遇到一個很麻煩的事情,就是一個json串中有很多佔位符,需要替換成特定文案。如果將json轉換成物件後,在一個一個屬性去轉換的話就出出現很多冗餘程式碼,不美觀也不是很實用。 而且也不能提前在json串中替換,因為替換的文案會因為某些變數發生改變。就比如國際化,在中文的時候應該是"你好",而在英文的

裝飾器 叠代器 生成器 面相過程 三元表達式 列表解析 序列

集合 cto 編寫 tor lec 列表解析 http 過程 可擴展性 裝飾器一 *args,**kwargs def index(name,age): print(name,age) def wrapper(*args,**kwargs):

深度剖析PHP序列和反序列

私有 class 文件 對象序列化 bpa php應用 OS 個人博客 def 序列化 序列化格式 在PHP中,序列化用於存儲或傳遞 PHP 的值的過程中,同時不丟失其類型和結構。 序列化函數原型如下: string serialize ( mixed $value ) 先

Android框架原始碼解析之()Picasso

這次要分析的原始碼是 Picasso 2.5.2 ,四年前的版本,用eclipse寫的,但不影響這次我們對其原始碼的分析 地址:https://github.com/square/picasso/tree/picasso-parent-2.5.2 Picasso的簡單使用

Spring原始碼解析(十)——AOP原理——AnnotationAwareAspectJAutoProxyCreator執行時機

     *             AnnotationAwareAspectJAutoProxyCreator => InstantiationAwareBean

Java物件深度複製和序列總結

經常會碰到物件複製的問題,這個問題比較基礎,同時與JVM記憶體模型掛鉤。 1. 實現Cloneable介面預設的clone方法是淺拷貝 Java Cloneable介面實際上是個空介面,沒有任何方法,實際的clone()是object的方法,但是是一個protected的方法,因此需

Java中使用FastJSON進行物件的序列和反序列

Java中使用FastJSON進行物件的序列化和反序列化 1.新增依賴,maven的pom.xml檔案中新增以下依賴 <dependency> <groupId>com.alibaba</groupId> <arti

螞蟻金服通訊框架SOFABolt解析 |序列機制(Serializer)

SOFA Scalable Open Financial Architecture 是螞蟻金服自主研發的金融級分散式中介軟體,包含了構建金融級雲原生架構所需的各個元件,是在金融場景裡錘鍊出來的最佳實踐。 本文為《螞蟻金服通訊框架SOFABolt解析》系列第二篇,

Fastjson和jackson的序列小知識

在使用Fastjson和Jackson對物件進行序列化時,針對物件的get方法進行序列化(即使沒有顯示宣告屬性),不同的工具處理方式也有所不同,比如會處理掉大小寫,下劃線,數字,排序等等,如圖: public class TestClass { public String get2A(

junit原始碼解析--初始階段

OK,我們接著上篇整理。上篇部落格中已經列出的junit的幾個核心的類,這裡我們開始整理junit完整的生命週期。 JUnit 的完整生命週期分為 3 個階段:初始化階段、執行階段和結果捕捉階段。 這篇這裡先來整理下junit的初始化階段。也就是建立 Testcase

Android原始碼解析之()-->HandlerThread

上一篇文章中我們講解了AsyncTast的基本使用以及實現原理,我們知道AsyncTask內部是通過執行緒池和Handler實現的,通過對執行緒池和handler的封裝實現了對非同步任務操作。更多關於AsyncTask相關的內容,可參考我的android原始

Vue 原始碼解析 - 例項 Vue 前(二)

前言 上一篇文章,大概的講解了Vue例項化前的一些配置,如果沒有看到上一篇,通道在這裡:Vue 原始碼解析 - 例項化 Vue 前(一) 在上一篇的結尾,我說這一篇後著重講一下 defineReactive 這個方法,這個方法,其實就是大家可以在外面看見一些文章對 vue 實現資料雙向繫結原理的過程。

fastjson 過濾不需要序列的屬性

JavaJSON技術框架選型與例項 JSON JSON英文全稱為JavaScriptObject Natation,採用key:value鍵值對的方式存貯資料,與xml格式相比,JSON是一種輕量級的資料交換格式;不要被Javascript這個單詞迷惑,實際上JSON只是

FastJson實現複雜物件序列與反序列

一.認識FastJson 1.優勢 fastjson是目前java語言中最快的json庫,比自稱最快的jackson速度要快,第三方獨立測試結果說明比gson快大約6倍,fastjson採用獨創的演算法,將parse的速度提升到極致,超過所有json庫。 FastJson速

Retrofit原始碼解析---初始

首先看下demo 1、首先定義請求模版介面 public interface IServiceDemo { @POST("login/nameAuth") Call<String> login( @Body User ue

springmvc原始碼解析之DispatcherServlet

開發十年,就只剩下這套架構體系了! >>>