空間站

          北極心空

            BlogJava :: 首頁 :: 聯系 :: 聚合  :: 管理
            15 Posts :: 393 Stories :: 160 Comments :: 0 Trackbacks

          JsonPlugin在分析類結構并序列化時,對于CGLig動態生成的類也是按照一般類來看待的。這就導致了如下的問題:

          在一個應用中,某些情況下,一個服務類返回的實體并不是原有實體類的對象,而是CGLib動態生成的子類。例如使用Hibernate的時候,某些情況下DAO返回的是EntityClassName$$EnhancerByCGLIB$$ac21e這樣的類的對象。Hibernate在這個子類中添加了hibernateLazyInitializer等等的附加屬性。由于jsonplugin并不區分類和動態生成的類,所以也會試圖序列化hibernateLazyInitializer屬性,從而導致出現如下的異常:

          java.sql.SQLException: Positioned Update not supported.
           at com.mysql.jdbc.ResultSet.getCursorName(ResultSet.java:1800)

          另外,CGLIB生成的類,某些方法上的@JSON標記奇怪的丟失了。導致標記了@JSON(serialize=false)的屬性也被序列化。

          在網上查了很久沒有發現相關的文章,所以無奈就自己動手修改jsonplugin的代碼了。

          類:com.googlecode.jsonplugin.JSONWriter,修改bean()方法:

           1     private void bean(Object object) throws JSONException {
           2         this.add("{");
           3 
           4         BeanInfo info;
           5 
           6         try {
           7             Class clazz = object.getClass();
           8 
           9             info = ((object == this.root) && this.ignoreHierarchy) ? Introspector
          10                     .getBeanInfo(clazz, clazz.getSuperclass())
          11                     : Introspector.getBeanInfo(clazz);
          12 
          13             PropertyDescriptor[] props = info.getPropertyDescriptors();
          14 
          15             boolean hasData = false;
          16             for (int i = 0; i < props.length; ++i) {
          17                 PropertyDescriptor prop = props[i];
          18                 String name = prop.getName();
          19                 Method accessor = prop.getReadMethod();
          20                 Method baseAccessor = null//這里增加一個臨時變量作為真實希望序列化的屬性的accessor方法引用
          21                 if (clazz.getName().indexOf("$$EnhancerByCGLIB$$"> -1) {  //如果是CGLIB動態生成的類
          22                     try {
          23                         //下面的邏輯是根據CGLIB動態生成的類名,得到原本的實體類名
          24                         //例如 EntityClassName$$EnhancerByCGLIB$$ac21e這樣
          25                         //的類,將返回的是EntityClassName這個類中的相應方法,若
          26                         //獲取不到對應方法,則說明要序列化的屬性例如hibernateLazyInitializer之類
          27                         //不在原有實體類中,而是僅存在于CGLib生成的子類中,此時baseAccessor
          28                         //保持為null
          29                         baseAccessor = Class.forName(
          30                                 clazz.getName().substring(0,
          31                                         clazz.getName().indexOf("$$")))
          32                                 .getDeclaredMethod(accessor.getName(),
          33                                         accessor.getParameterTypes());
          34                     } catch (Exception ex) {
          35                         log.debug(ex.getMessage());
          36                     }
          37                 }
          38                 else    //若不是CGLib生成的類,那么要序列化的屬性的accessor方法就是該類中的方法。
          39                     baseAccessor = accessor;
          40 
          41                 //這個判斷,根據上面的邏輯,使得僅存在于CGLIB生成子類中的屬性跳過JSON序列化
          42                 if (baseAccessor != null) {    
          43                     
          44                     //下面的JSON Annotation的獲取也修改為從baseAccessor獲取,這樣避免了
          45                     //由于CGLIB生成子類而導致某些方法上的JSON Annotation丟失導致處理不該
          46                     //序列化的屬性
          47                     JSON json = baseAccessor.getAnnotation(JSON.class);
          48                     if (json != null) {
          49                         if (!json.serialize())
          50                             continue;
          51                         else if (json.name().length() > 0)
          52                             name = json.name();
          53                     }
          54 
          55                     //ignore "class" and others
          56                     if (this.shouldExcludeProperty(clazz, prop)) {
          57                         continue;
          58                     }
          59                     String expr = null;
          60                     if (this.buildExpr) {
          61                         expr = this.expandExpr(name);
          62                         if (this.shouldExcludeProperty(expr)) {
          63                             continue;
          64                         }
          65                         expr = this.setExprStack(expr);
          66                     }
          67                     if (hasData) {
          68                         this.add(',');
          69                     }
          70                     hasData = true;
          71 
          72                     Object value = accessor.invoke(object, new Object[0]);
          73                     this.add(name, value, accessor);
          74                     if (this.buildExpr) {
          75                         this.setExprStack(expr);
          76                     }
          77                 }
          78             }
          79         } catch (Exception e) {
          80             throw new JSONException(e);
          81         }
          82 
          83         this.add("}");
          84     }

          這樣修改之后,原有類中不能存在的屬性將不會被序列化,同時,由于不檢查生成的類的方法上的JSON標記,而是檢查原有類上的標記,這樣避免了由于CGLIB導致的Annotation丟失的問題。

          在此依然向諸位詢問是否JSONPlugin有處理這樣的情況的方法。
          posted on 2008-05-28 18:26 蘆葦 閱讀(1797) 評論(1)  編輯  收藏 所屬分類: Struts

          Feedback

          # re: 當JsonPlugin遇到CGLib 2009-09-22 22:33 林浩新
          JSONConfig jsonConfig=new JSONConfig();
          jsonConfig.setExcludes(new String[]{'hibernateLazyInitializer'});
          JSONObject jo=JSONObject.fromObject(user,jsonConfig);
          這樣可以解決掉這個問題  回復  更多評論
            

          主站蜘蛛池模板: 乌拉特中旗| 比如县| 池州市| 宁都县| 松江区| 民乐县| 六安市| 岗巴县| 道真| 台东市| 长汀县| 华容县| 五华县| 梧州市| 江陵县| 会理县| 广水市| 东阳市| 明溪县| 朝阳区| 江安县| 钦州市| 古田县| 威宁| 宜丰县| 澜沧| 安仁县| 左云县| 西平县| 塔河县| 永善县| 抚宁县| 岗巴县| 甘南县| 醴陵市| 汕头市| 靖西县| 新丰县| 井研县| 大竹县| 甘谷县|