在Java中的模型關(guān)系設(shè)計(jì)中,循環(huán)的關(guān)系是很常見(jiàn)的,特別是ORM的出現(xiàn),關(guān)系的循環(huán)更加有利于維護(hù)各自的狀態(tài)。但就是這種循環(huán)的關(guān)系,在java對(duì)象序列化時(shí),不可避免的會(huì)導(dǎo)致循環(huán)引用(Cycle Reference)的問(wèn)題。
導(dǎo)致CycleReference的情況
還是舉個(gè)例子吧(代碼說(shuō)話):一個(gè)很典型,很常見(jiàn)的雙向引用的對(duì)象關(guān)系。

2

3

4

5

6

7


8

9

10

11


12

13

14

15

16

17



18

19

20

21

22

23

24

25

26

27


28

29

30

31

32

33

34

35

36

37



38

39

40

41

另外一種導(dǎo)致這個(gè)問(wèn)題的情況是,多個(gè)對(duì)象間關(guān)系形成一條回路,跟電學(xué)有點(diǎn)像。(具體就不舉例了,在模型設(shè)計(jì)時(shí),最好還是避免出現(xiàn)這種情況。)
導(dǎo)致這種問(wèn)題的原因
用jaxb(如果沒(méi)有特殊解釋,本文采用的都是jaxb)序列化Company時(shí),無(wú)疑會(huì)發(fā)生循環(huán)引用。
當(dāng)序列化引擎解析Company時(shí),它發(fā)現(xiàn)這個(gè)對(duì)象持有一個(gè)Employee的引用,轉(zhuǎn)而去騷擾Employee。解析Employee時(shí),發(fā)現(xiàn)他又持有Company的引用,又轉(zhuǎn)回Company。如此問(wèn)題產(chǎn)生。
引擎它并不知道在遇到循環(huán)引用問(wèn)題時(shí),該怎么處理,它只是忠實(shí)得按照固定的算法去執(zhí)行任務(wù)。所以我們得讓引擎聰明點(diǎn),我們得讓引擎遇到這種問(wèn)題有處理機(jī)制。
解決問(wèn)題
既然需要引擎更聰明,那就沒(méi)辦法,就得燒香拜佛,希望制造商的產(chǎn)品擴(kuò)展性足夠好,考慮了足夠多的情況。
幸運(yùn)的是,jaxb提供了有這種擴(kuò)展。(CycleRecoverable接口)
行軍打仗(例子先行):(將以上的例子改下)

2

3

4

5

6

7


8

9

10

11


12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29



30

31

32

33

34

35

36

37

38

39


40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59



60

61

62

63

注意到onCycleDetected方法就是一個(gè)回調(diào)方法,當(dāng)遇到循環(huán)引用時(shí),jaxb引擎會(huì)調(diào)用這個(gè)方法,用return對(duì)象來(lái)替換this。所以在這個(gè)過(guò)程中,就可以將引起循環(huán)引用問(wèn)題的關(guān)系斷開(kāi),返回給jaxb。
當(dāng)然Company和Employee對(duì)象沒(méi)必要全部實(shí)現(xiàn)CycleRecoverable接口,但是拿到現(xiàn)實(shí)的模型圖中去,誰(shuí)也保證不了他們不跟別的對(duì)象有循環(huán)的關(guān)系存在。因此還是建議大家把模型都實(shí)現(xiàn)這個(gè)接口,也好一勞永逸。
希望大家得到了想要的東西。
Thanks。