如鹏网 大学生计算机学习社区

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开源团队 阅读(344) 评论(0)  编辑  收藏

只有注册用户登录后才能发表评论。


网站导航: