如鵬網 大學生計算機學習社區

          CowNew開源團隊

          http://www.cownew.com 郵件請聯系 about521 at 163.com

            BlogJava :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理 ::
            363 隨筆 :: 2 文章 :: 808 評論 :: 0 Trackbacks

          為了鞏固 CGLib 的知識,下面我們實現一個稍微復雜一點的例子。

          例、請實現一個攔截器,使其能夠檢測一個 JavaBean 的哪些字段改變了。

          1 )首先定義一個 JavaBean

          public class PersonInfo

          {

          ???? private String name;

          ?

          ???? private String email;

          ?

          ???? private int age;

          ?

          ???? private String address;

          ?

          ???? public String getEmail()

          ???? {

          ???????? return email;

          ???? }

          ?

          ???? public void setEmail(String email)

          ???? {

          ???????? this.email = email;

          ???? }

          ?

          ???? public String getName()

          ???? {

          ???????? return name;

          ???? }

          ?

          ???? public void setName(String name)

          ???? {

          ???????? this.name = name;

          ???? }

          ?

          ???? public String getAddress()

          ???? {

          ???????? return address;

          ???? }

          ?

          ???? public void setAddress(String address)

          ???? {

          ???????? this.address = address;

          ???? }

          ?

          ???? public int getAge()

          ???? {

          ???????? return age;

          ???? }

          ?

          ???? public void setAge(int age)

          ???? {

          ???????? this.age = age;

          ???? }

          }

          2 )定義一個 MethodInterceptor ,這一步是最關鍵的

          import java.lang.reflect.Method;

          import java.util.Collections;

          import java.util.HashSet;

          import java.util.Set;

          ?

          import net.sf.cglib.proxy.MethodInterceptor;

          import net.sf.cglib.proxy.MethodProxy;

          ?

          public class JavaBeanDataChangeInterceptor implements MethodInterceptor

          {

          ???? private static final String SET = "set";

          ?

          ???? private Set changedPropSet;

          ?

          ???? public JavaBeanDataChangeInterceptor()

          ???? {

          ???????? changedPropSet = new HashSet();

          ???? }

          ?

          ???? public Object intercept(Object obj, Method method, Object[] args,

          ????????????? MethodProxy proxy) throws Throwable

          ???? {

          ???????? String name = method.getName();

          ???????? if (name.startsWith(SET))

          ???????? {

          ????????????? String s = name.substring(SET.length());

          ????????????? changedPropSet.add(s);

          ???????? }

          ???????? return proxy.invokeSuper(obj, args);

          ???? }

          ?

          ???? public Set getChangedPropSet()

          ???? {

          ???????? return Collections.unmodifiableSet(changedPropSet);

          ???? }

          ?

          ???? public void reset()

          ???? {

          ???????? changedPropSet.clear();

          ???? }

          }

          定義一個集合 changedPropSet 用來存放修改了的字段名,增加了一個方法 reset 用來清空此集合,增加了一個 getChangedPropSet 方法用來供外界得到修改了的字段,為了防止調用者對 changedPropSet 做修改,因此我們采用 Collections.unmodifiableSet 對返回的集合進行不可修改的修飾。

          intercept 方法中,我們判斷如果被調用的方法以 set 開頭,則把此字段名放入 changedPropSet 集合中。

          3 )定義剖析用工具類。

          import net.sf.cglib.proxy.Callback;

          import net.sf.cglib.proxy.Factory;

          ?

          public class JavaBeanInterceptorUtils

          {

          ???? public static JavaBeanDataChangeInterceptor getInterceptor(

          ????????????? Object obj)

          ???? {

          ???????? if (!(obj instanceof Factory))

          ???????? {

          ????????????? return null;

          ???????? }

          ???????? Factory f = (Factory) obj;

          ???????? Callback[] callBacks = f.getCallbacks();

          ???????? for (int i = 0, n = callBacks.length; i < n; i++)

          ???????? {

          ????????????? Callback callBack = callBacks[i];

          ????????????? if (callBack instanceof JavaBeanDataChangeInterceptor)

          ????????????? {

          ?????????????????? return (JavaBeanDataChangeInterceptor) callBack;

          ????????????? }

          ???????? }

          ???????? return null;

          ???? }

          }

          這個 JavaBeanInterceptorUtils 只有一個方法 getInterceptor ,這個方法用于從一個被 CGLib 代理的 JavaBean 中取出攔截器 JavaBeanDataChangeInterceptor

          前邊提到了, CGLib 實現攔截的方式就是生成被攔截類的子類,這個子類實現了 net.sf.cglib.proxy.Factory 接口,這個接口中有一個非常重要的方法 getCallbacks() ,通過這個方法我們可以得到所有的攔截器

          4 主程序

          public class MainApp

          {

          ???? public static void main(String[] args)

          ???? {

          ???????? Enhancer enhancer = new Enhancer();

          ???????? enhancer.setSuperclass(PersonInfo.class);

          ???????? enhancer.setCallback(new JavaBeanDataChangeInterceptor());

          ?

          ???????? PersonInfo info = (PersonInfo) enhancer.create();

          ???????? // 對生成的 JavaBean 做一些初始化

          ???????? info.setAddress(" 地址 1");

          ???????? info.setAge(21);

          ???????? info.setName("tom");

          ?

          ???????? // 得到攔截器

          ???????? JavaBeanDataChangeInterceptor interceptor = JavaBeanInterceptorUtils

          ?????????????????? .getInterceptor(info);

          ???????? // 復位修改字段記錄集合

          ???????? interceptor.reset();

          ?

          ???????? // JavaBean 做一些修改

          ???????? editPersonInf(info);

          ?

          ???????? // 得到修改了的字段

          ???????? Iterator it = interceptor.getChangedPropSet().iterator();

          ???????? while (it.hasNext())

          ???????? {

          ????????????? System.out.println(it.next());

          ???????? }

          ???? }

          ?

          ???? private static void editPersonInf(PersonInfo info)

          ???? {

          ???????? info.setName("Jim");

          ???????? info.setAddress("N.Y Street");

          ???? }

          }???

          運行結果:

          Address

          Name

          ?

          這個“變化字段攔截器”是有一定實際意義的,比如可以用來實現“只保存修改了的字段以提高效率”等功能

          ?

          很多資料中都說如果要使用 JDK Proxy ,被代理的對象的類必須要實現接口,這種說法是不嚴謹的。從上邊的例子我們可以看出,正確的說法應該是:如果要使用 JDK Proxy ,那么我們要通過代理調用的方法必須定義在一個接口中。“面向接口編程而不是面向實現編程”是 OOP 開發中的一條基本原則,因此這種限制并不會對我們的開發造成障礙。

          posted on 2007-02-20 00:50 CowNew開源團隊 閱讀(353) 評論(0)  編輯  收藏

          只有注冊用戶登錄后才能發表評論。


          網站導航:
           
          主站蜘蛛池模板: 稻城县| 建阳市| 西安市| 南康市| 曲阜市| 土默特左旗| 池州市| 高陵县| 定日县| 镇远县| 嘉义市| 西乡县| 榕江县| 云南省| 垫江县| 宁阳县| 通化县| 门头沟区| 平安县| 宁河县| 双桥区| 云霄县| 安泽县| 石渠县| 和林格尔县| 体育| 英德市| 浦县| 正镶白旗| 印江| 治县。| 枣强县| 夏邑县| 会东县| 文安县| 新绛县| 尚义县| 饶河县| 榆社县| 庄河市| 白沙|