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

          CowNew開源團(tuán)隊

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

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

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

          例、請實現(xiàn)一個攔截器,使其能夠檢測一個 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 ,這一步是最關(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();

          ???? }

          }

          定義一個集合 changedPropSet 用來存放修改了的字段名,增加了一個方法 reset 用來清空此集合,增加了一個 getChangedPropSet 方法用來供外界得到修改了的字段,為了防止調(diào)用者對 changedPropSet 做修改,因此我們采用 Collections.unmodifiableSet 對返回的集合進(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;

          ???? }

          }

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

          前邊提到了, CGLib 實現(xiàn)攔截的方式就是生成被攔截類的子類,這個子類實現(xiàn)了 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);

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

          ???????? 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");

          ???? }

          }???

          運行結(jié)果:

          Address

          Name

          ?

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

          ?

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

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

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


          網(wǎng)站導(dǎo)航:
          博客園   IT新聞   Chat2DB   C++博客   博問  
           
          主站蜘蛛池模板: 武清区| 南安市| 兰西县| 清河县| 蕲春县| 大宁县| 新兴县| 介休市| 临清市| 娱乐| 临海市| 来宾市| 中西区| 吕梁市| 岳西县| 钟山县| 金堂县| 贡山| 邯郸市| 芷江| 饶河县| 左云县| 额敏县| 商南县| 沅江市| 淮北市| 囊谦县| 昭觉县| 新乡县| 沙河市| 永善县| 江都市| 双柏县| 福建省| 沁源县| 金寨县| 潮安县| 江北区| 吴忠市| 榆中县| 大化|