首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > 编程 >

喜新别厌旧 - 妥妥处理新旧库兼容性有关问题的一个方法 - 运用java反射+代理思想

2012-11-03 
喜新别厌旧 - 妥妥处理新旧库兼容性问题的一个方法 - 运用java反射+代理思想? ? 地球上的程序员都知道,当

喜新别厌旧 - 妥妥处理新旧库兼容性问题的一个方法 - 运用java反射+代理思想

? ? 地球上的程序员都知道,当自己发布一个新版本库的时候,一定要注意向上下左右前后东南西北中发白各个方向的兼容性,尽可能做到最大程度的兼容。

? ? 然而还有另外一种情况 -- 如果自己依赖的库,某天升级后新旧版本间有少量不兼容,这时该怎么办?最直接的办法是也随着它拆分为两个版本,适用于绝大部分情况,但是也有额外的维护负担等缺点;此外如果这个第三方库并不是那么重要,或者其不兼容的地方不是特别多的话,那么为了它而拆分就没必要了。

? ? 记录下这个有两个目的,一个是分享一下实际项目中遇到这个兼容性问题是如何解决的;另外就是看看朋友们有没有其它的思路可以再开拓一下。

? ? 下面就用简化过的代码来说明一下问题以及解决思路:

? ? (1)第三方库的第一个版本中,有一个业务函数可供调用:

?

package org.otherlib;public class Otherlib{public static String getLibVersion(){return "Otherlib V1.0 (use static method)";}// others... ...}

?

? ? ?(2)自己的库中,用到了这个函数

?

package com.iteye.goonfly;import org.otherlib.*;public class Ourlib{public static void main(String[] args){System.out.println("==== Using lib : " + Otherlib.getLibVersion() + " ====");}}

?

? ? ?编译运行如下:

?

$javac -d ./classes/ otherlib1/Otherlib.java$javac -cp ./classes/ -d ./classes/ oursrc/Ourlib.java$java -cp ./classes/ com.iteye.goonfly.Ourlib==== Using lib : Otherlib V1.0 (use static method) ====

?

? ? ?(3)第三方库的第二个版本,删掉了这个函数,改用了静态常量字符串

?

package org.otherlib;public class Otherlib{public static final String LIB_VERSION = "Otherlib V2.0 (use static String)";// others... ...}

?

? ? ?这种情况下,可以逐个修改自己的库里面的调用处代码,与之新版本对应:

?

package com.iteye.goonfly;import org.otherlib.*;public class Ourlib2{public static void main(String[] args){//System.out.println("Using lib : " + Otherlib.getLibVersion());System.out.println("==== Using lib : " + Otherlib.LIB_VERSION + " ====");}}

?

? ? ?但是问题则是,自己的库与第三方库新版本可以配合适用,和旧版本则不行了,喜新厌旧,恐怕要出大事。。。


? ? 由于兼容性的问题不大(不是逻辑上的架构上的或者有大量的接口变更等),所以除了也随着发布两个版本外,还可以采用“反射机制+代理思想,用一个自己的库,可以同时兼容两个版本的第三方库,代码如下:

? ? (4)自己库的新版本,不再直接调用有变更的地方,而是调用代理类,差异的部分,让代理通过反射处理

?

package com.iteye.goonfly;//import org.otherlib.*;public class Ourlib3{public static void main(String[] args){//System.out.println("Using lib : " + Otherlib.getLibVersion());System.out.println("==== Using lib : " + OtherlibProxy.getLibVersion() + " ====");}}

?

? ? (5)新增的代理类

package com.iteye.goonfly;import java.lang.reflect.Field;import java.lang.reflect.InvocationTargetException;import java.lang.reflect.Method;public class OtherlibProxy{public static String getLibVersion(){Class clazz = null;try {clazz = Class.forName("org.otherlib.Otherlib");} catch (ClassNotFoundException e) {e.printStackTrace();}if(null == clazz){return "!!!!Class org.otherlib.Otherlib NOT found!!!!";}try {// if it has getLibVersionMethod() methodMethod getLibVersionMethod = clazz.getMethod("getLibVersion", new Class[0]);return (String)getLibVersionMethod.invoke(null, new Object[0]);} catch (NoSuchMethodException e) {e.printStackTrace();} catch (IllegalAccessException e) {e.printStackTrace();} catch (InvocationTargetException e) {e.printStackTrace();}try {// or else it has the static string fieldField field = clazz.getField("LIB_VERSION");return (String)field.get(clazz);} catch (SecurityException e) {e.printStackTrace();} catch (NoSuchFieldException e) {e.printStackTrace();} catch (IllegalAccessException e) {e.printStackTrace();}return "!!!!NO getLibVersion() method OR LIB_VERSION string found!!!!";}}

?

? ? (6)测试验证一下

先试试旧版本

?

$javac -d ./classes/ otherlib1/Otherlib.java$javac -cp ./classes/ -d ./classes/ oursrc/OtherlibProxy.java$javac -cp ./classes/ -d ./classes/ oursrc/Ourlib3.java$java -cp ./classes/ com.iteye.goonfly.Ourlib3==== Using lib : Otherlib V1.0 (use static method) ====

再试试新版本

?

$javac -d ./classes/ otherlib2/Otherlib.java$javac -cp ./classes/ -d ./classes/ oursrc/OtherlibProxy.java$javac -cp ./classes/ -d ./classes/ oursrc/Ourlib3.java$java -cp ./classes/ com.iteye.goonfly.Ourlib3java.lang.NoSuchMethodException: org.otherlib.Otherlib.getLibVersion()at java.lang.Class.getMethod(Class.java:1622)at com.iteye.goonfly.OtherlibProxy.getLibVersion(OtherlibProxy.java:22)at com.iteye.goonfly.Ourlib3.main(Ourlib3.java:8)==== Using lib : Otherlib V2.0 (use static String) ====

?

可以看到,抛出了异常,并且成功调用到了新版本库,测试一切正常后,捕获到异常不输出信息即可,将来的某一天,如果新版本把旧版本彻底的替换淘汰了,那就代理类里面修改一下,是不是design pattern相关的味道出来一点点了^_^

?

热点排行