Spring源码学习之GCLIB的简单理解

来源:互联网 发布:创客空间的编程 编辑:程序博客网 时间:2024/06/05 06:31

百度百科中对CGLIB的解释是这样的:CGLIB(Code Generation Library)是一个开源项目!是一个强大的,高性能,高质量的Code生成类库,它可以在运行期扩展Java类与实现Java接口。Hibernate用它来实现PO(Persistent Object 持久化对象)字节码的动态生成等。不仅如此,它还为spring aop提供了一个底层的实现。

下面就简单写一些代码感受一下gclib的作用:对表格的简单操作。

1.创建一个dao类

public class UserDAO {      public void save(){          System.out.println("save() is running !");      }      public void query(){          System.out.println("query() is running !");      }      public void update(){          System.out.println("update() is running !");      }      public void delete(){          System.out.println("delete() is running !");      }  } 
这就是一个我们做web开发所熟悉的javaBean,它提供基本的数据库操作:增删改查。

下面我们创建一个Dao工厂,用来生成dao实例:

public class DAOFactory {      private static UserDAO userDao = new UserDAO();      public static UserDAO getInstance(){          return userDao;      }  } 
创建一个测试类来调用CRUD方法:

public class Test {        public static void main(String[] args) {          UserDAO userDao = DAOFactory.getInstance();          doMethod(userDao);      }      public static void doMethod(UserDAO dao){          dao.save();        dao.query();          dao.update();          dao.delete();      }  }
运行上面的代码,CRUD会被正确的调用,其中并没有涉及cglib。然而变化随之而来,新需求要求这些数据操作功能不能开放给用户,只有“张三”才有权使用,难道我们要在每个方法上面进行判断吗? 显然不可行,Proxy可能是最好的解决办法。但是其中jdk的动态代理需要实现接口,这就要求我们的dao类改变了。既然不想改动dao又要使用代理,只有cglib了。 只需新增一个权限验证的方法拦截器。定义一个拦截器,在调用目标方法时,CGLib会回调MethodInterceptor接口方法拦截,来实现你自己的代理逻辑,类似于JDK中的InvocationHandler接口。

public class AuthProxy implements MethodInterceptor {      private String name ;      //传入用户名称      public AuthProxy(String name){          this.name = name;      }      public Object intercept(Object arg0, Method arg1, Object[] arg2,              MethodProxy arg3) throws Throwable {          //用户进行判断          if(!"张三".equals(name)){              System.out.println("你没有权限!");              return null;          }          return arg3.invokeSuper(arg0, arg2);      }  }  
然后对dao工厂进行修改,提供一个使用代理的实例生成方法:

public static UserDAO getAuthInstance(AuthProxy authProxy){      Enhancer en = new Enhancer();      //进行代理      en.setSuperclass(UserDAO.class);      en.setCallback(authProxy);      //生成代理实例      return (UserDAO)en.create();  } 
写一个测试类测试代码运行结果:

public class Test {        public static void main(String[] args) {          haveAuth();        haveNoAuth();    }      public static void haveAuth(){        UserDAO userDao = DAOFactory.getAuthInstance(new AuthProxy("张三"));          doMethod(userDao);      }     public static void haveNoAuth(){        UserDAO userDao = DAOFactory.getAuthInstance(new AuthProxy("李四"));          doMethod(userDao);      }    public static void doMethod(UserDAO dao){          dao.save();        dao.query();          dao.update();          dao.delete();      }  }
测试结果为:张三正常执行了,李四没有执行。这就是一个简单的aop。

现在除了"张三"其他人都用不了了,现在不可以这样。必须开放查询功能。当然最简单的方式是去修改我们的方法拦截器,不过这样会使逻辑变得复杂,且 不利于维护。还好CGlib给我们提供了方法过滤器(CallbackFilter),CallbackFilte可以明确表明,被代理的类中不同的方法,被哪个拦截器所拦截。下面我们就来做个过滤器用来过滤query方法。 

public class AuthProxyFilter implements CallbackFilter{      public int accept(Method arg0) {          if(!"query".equalsIgnoreCase(arg0.getName()))              return 0;          return 1;      }    } 
然后在dao工厂中新增一个方法:

public static UserDAO getAuthInstanceByFilter(AuthProxy authProxy){      Enhancer en = new Enhancer();      en.setSuperclass(UserDAO.class);      en.setCallbacks(new Callback[]{authProxy,NoOp.INSTANCE});      en.setCallbackFilter(new AuthProxyFilter());      return (UserDAO)en.create();  }
程序运行的结果是:张三可以执行CRUD,李四只可以执行查询方法。














0 0
原创粉丝点击