熱點推薦:
您现在的位置: 電腦知識網 >> 編程 >> Java編程 >> Java核心技術 >> 正文

CGLib實現變化字段探測的供能

2013-11-23 19:22:20  來源: Java核心技術 

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

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

  ( )首先定義一個 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)

  {

  thisemail = email;

  }

   

  public String getName()

  {

  return name;

  }

   

  public void setName(String name)

  {

  thisname = name;

  }

   

  public String getAddress()

  {

  return address;

  }

   

  public void setAddress(String address)

  {

  thisaddress = address;

  }

   

  public int getAge()

  {

  return age;

  }

   

  public void setAge(int age)

  {

  thisage = age;

  }

  }

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

  import javalangreflectMethod;

  import javautilCollections;

  import javautilHashSet;

  import javautilSet;

   

  import netsfcglibproxyMethodInterceptor;

  import netsfcglibproxyMethodProxy;

   

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

  if (namestartsWith(SET))

  {

  String s = namesubstring(SETlength());

  changedPropSetadd(s);

  }

  return proxyinvokeSuper(obj args);

  }

   

  public Set getChangedPropSet()

  {

  return CollectionsunmodifiableSet(changedPropSet);

  }

   

  public void reset()

  {

  changedPropSetclear();

  }

  }

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

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

  ( )定義剖析用工具類

  import netsfcglibproxyCallback;

  import netsfcglibproxyFactory;

   

  public class JavaBeanInterceptorUtils

  {

  public static JavaBeanDataChangeInterceptor getInterceptor(

  Object obj)

  {

  if (!(obj instanceof Factory))

  {

  return null;

  }

  Factory f = (Factory) obj;

  Callback[] callBacks = fgetCallbacks();

  for (int i = n = callBackslength; i < n; i++)

  {

  Callback callBack = callBacks[i];

  if (callBack instanceof JavaBeanDataChangeInterceptor)

  {

  return (JavaBeanDataChangeInterceptor) callBack;

  }

  }

  return null;

  }

  }

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

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

  ( ) 主程序

  public class MainApp

  {

  public static void main(String[] args)

  {

  Enhancer enhancer = new Enhancer();

  enhancersetSuperclass(PersonInfoclass);

  enhancersetCallback(new JavaBeanDataChangeInterceptor());

   

  PersonInfo info = (PersonInfo) enhancercreate();

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

  infosetAddress( 地址 );

  infosetAge();

  infosetName(tom);

   

  // 得到攔截器

  JavaBeanDataChangeInterceptor interceptor = JavaBeanInterceptorUtils

  getInterceptor(info);

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

  interceptorreset();

   

  // 對 JavaBean 做一些修改

  editPersonInf(info);

   

  // 得到修改了的字段

  Iterator it = interceptorgetChangedPropSet(erator();

  while (ithasNext())

  {

  Systemoutprintln(itnext());

  }

  }

   

  private static void editPersonInf(PersonInfo info)

  {

  infosetName(Jim);

  infosetAddress(NY Street);

  }

  }   

  運行結果

  Address

  Name

   

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

   

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


From:http://tw.wingwit.com/Article/program/Java/hx/201311/26735.html
    推薦文章
    Copyright © 2005-2013 電腦知識網 Computer Knowledge   All rights reserved.