如鵬網(wǎng) 大學(xué)生計(jì)算機(jī)學(xué)習(xí)社區(qū)

          CowNew開源團(tuán)隊(duì)

          http://www.cownew.com 郵件請(qǐng)聯(lián)系 about521 at 163.com

            BlogJava :: 首頁 :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理 ::
            363 隨筆 :: 2 文章 :: 808 評(píng)論 :: 0 Trackbacks

          為了鞏固 CGLib 的知識(shí),下面我們實(shí)現(xiàn)一個(gè)稍微復(fù)雜一點(diǎn)的例子。

          例、請(qǐng)實(shí)現(xiàn)一個(gè)攔截器,使其能夠檢測(cè)一個(gè) JavaBean 的哪些字段改變了。

          1 )首先定義一個(gè) 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 )定義一個(gè) MethodInterceptor ,這一步是最關(guān)鍵的

          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();

          ???? }

          }

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

          intercept 方法中,我們判斷如果被調(diào)用的方法以 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;

          ???? }

          }

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

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

          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();

          ???????? // 對(duì)生成的 JavaBean 做一些初始化

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

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

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

          ?

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

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

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

          ???????? // 復(fù)位修改字段記錄集合

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

          ?

          ???????? // 對(duì) 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");

          ???? }

          }???

          運(yùn)行結(jié)果:

          Address

          Name

          ?

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

          ?

          很多資料中都說如果要使用 JDK Proxy ,被代理的對(duì)象的類必須要實(shí)現(xiàn)接口,這種說法是不嚴(yán)謹(jǐn)?shù)摹纳线叺睦游覀兛梢钥闯觯_的說法應(yīng)該是:如果要使用 JDK Proxy ,那么我們要通過代理調(diào)用的方法必須定義在一個(gè)接口中。“面向接口編程而不是面向?qū)崿F(xiàn)編程”是 OOP 開發(fā)中的一條基本原則,因此這種限制并不會(huì)對(duì)我們的開發(fā)造成障礙。

          posted on 2007-02-20 00:50 CowNew開源團(tuán)隊(duì) 閱讀(350) 評(píng)論(0)  編輯  收藏

          只有注冊(cè)用戶登錄后才能發(fā)表評(píng)論。


          網(wǎng)站導(dǎo)航:
           
          主站蜘蛛池模板: 阳西县| 大方县| 荔浦县| 开平市| 梁平县| 华坪县| 紫云| 奈曼旗| 高陵县| 鄂伦春自治旗| 许昌县| 旅游| 锡林浩特市| 莆田市| 子长县| 玛多县| 本溪| 肥乡县| 融水| 信阳市| 西宁市| 宜兰县| 绥江县| 夏河县| 铜鼓县| 崇文区| 仪陇县| 肃宁县| 崇仁县| 长顺县| 永安市| 剑河县| 吉安市| 武隆县| 旬阳县| 凤山市| 印江| 皋兰县| 永登县| 天柱县| 垫江县|