JsonPlugin在分析類結(jié)構(gòu)并序列化時(shí),對(duì)于CGLig動(dòng)態(tài)生成的類也是按照一般類來看待的。這就導(dǎo)致了如下的問題:

在一個(gè)應(yīng)用中,某些情況下,一個(gè)服務(wù)類返回的實(shí)體并不是原有實(shí)體類的對(duì)象,而是CGLib動(dòng)態(tài)生成的子類。例如使用Hibernate的時(shí)候,某些情況下DAO返回的是EntityClassName$$EnhancerByCGLIB$$ac21e這樣的類的對(duì)象。Hibernate在這個(gè)子類中添加了hibernateLazyInitializer等等的附加屬性。由于jsonplugin并不區(qū)分類和動(dòng)態(tài)生成的類,所以也會(huì)試圖序列化hibernateLazyInitializer屬性,從而導(dǎo)致出現(xiàn)如下的異常:

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

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

在網(wǎng)上查了很久沒有發(fā)現(xiàn)相關(guān)的文章,所以無奈就自己動(dòng)手修改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//這里增加一個(gè)臨時(shí)變量作為真實(shí)希望序列化的屬性的accessor方法引用
21                 if (clazz.getName().indexOf("$$EnhancerByCGLIB$$"> -1) {  //如果是CGLIB動(dòng)態(tài)生成的類
22                     try {
23                         //下面的邏輯是根據(jù)CGLIB動(dòng)態(tài)生成的類名,得到原本的實(shí)體類名
24                         //例如 EntityClassName$$EnhancerByCGLIB$$ac21e這樣
25                         //的類,將返回的是EntityClassName這個(gè)類中的相應(yīng)方法,若
26                         //獲取不到對(duì)應(yīng)方法,則說明要序列化的屬性例如hibernateLazyInitializer之類
27                         //不在原有實(shí)體類中,而是僅存在于CGLib生成的子類中,此時(shí)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                 //這個(gè)判斷,根據(jù)上面的邏輯,使得僅存在于CGLIB生成子類中的屬性跳過JSON序列化
42                 if (baseAccessor != null) {    
43                     
44                     //下面的JSON Annotation的獲取也修改為從baseAccessor獲取,這樣避免了
45                     //由于CGLIB生成子類而導(dǎo)致某些方法上的JSON Annotation丟失導(dǎo)致處理不該
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     }

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

在此依然向諸位詢問是否JSONPlugin有處理這樣的情況的方法。