CGlib是什么?
CGlib是一个强大的,高性能,高质量的Code生成类库。它能够在运行期扩展Java类与实现Java接口。
固然这些实际的功能是asm所提供的,asm又是什么?Java字节码操控框架,具体是什么你们能够上网查一查,毕竟咱们这里所要讨论的是cglib,
cglib就是封装了asm,简化了asm的操做,实现了在运行期动态生成新的class。
可能你们还感受不到它的强大,如今就告诉你。
实际上CGlib为spring aop提供了底层的一种实现;为hibernate使用cglib动态生成VO/PO (接口层对象)。
下面咱们将经过一个具体的事例来看一下CGlib体验一下CGlib。
* CGlib 2.13
* ASM 2.23
以一个实例在简单介绍下cglib的应用。
咱们模拟一个虚拟的场景,模拟对表的操做。
1. 开始咱们对表提供了CRUD方法。
咱们如今建立一个对Table操做的DAO类。 java
Java代码
spring
- public class TableDAO {
- public void create(){
- System.out.println("create() 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 !");
- }
- }
OK,它就是一个javaBean,提供了CRUD方法的javaBean。
下面咱们建立一个DAO工厂,用来生成DAO实例。 框架
Java代码
性能
- public class TableDAOFactory {
- private static TableDAO tDao = new TableDAO();
- public static TableDAO getInstance(){
- return tDao;
- }
- }
接下来咱们建立客户端,用来调用CRUD方法。 this
Java代码
hibernate
- public class Client {
-
- public static void main(String[] args) {
- TableDAO tableDao = TableDAOFactory.getInstance();
- doMethod(tableDao);
- }
- public static void doMethod(TableDAO dao){
- dao.create();
- dao.query();
- dao.update();
- dao.delete();
- }
- }
OK,完成了,CRUD方法彻底被调用了。固然这里并无CGlib的任何内容。问题不会这么简单的就结束,新的需求来临了。
2. 变化随之而来,Boss告诉咱们这些方法不能开放给用户,只有“张三”才有权使用。阿~!怎么办,难道咱们要在每一个方法上面进行判断吗?
好像这么作也太那啥了吧,对了对了Proxy多是最好的解决办法。jdk的代理就能够解决了。 好了咱们来动手改造吧。等等jdk的代理须要实现接口,这样,
咱们的dao类须要改变了。既然不想改动dao又要使用代理,咱们这就请出CGlib。
咱们只需新增一个权限验证的方法拦截器。 代理
Java代码
对象
- 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工厂进行修改,咱们提供一个使用代理的实例生成方法 接口
Java代码
get
- public static TableDAO getAuthInstance(AuthProxy authProxy){
- Enhancer en = new Enhancer();
- //进行代理
- en.setSuperclass(TableDAO.class);
- en.setCallback(authProxy);
- //生成代理实例
- return (TableDAO)en.create();
- }
咱们这就能够看看客户端的实现了。添加了两个方法用来验证不一样用户的权限。
Java代码 
- public static void haveAuth(){
- TableDAO tDao = TableDAOFactory.getAuthInstance(new AuthProxy("张三"));
- doMethod(tDao);
- }
- public static void haveNoAuth(){
- TableDAO tDao = TableDAOFactory.getAuthInstance(new AuthProxy("李四"));
- doMethod(tDao);
- }
OK,"张三"的正常执行,"李四"的没有执行。
看到了吗?简单的aop就这样实现了
难道就这样结束了么?
3. Boss又来训话了,不行不行,如今除了"张三"其余人都用不了了,如今不能够这样。他们都来向我反映了,必须使用开放查询功能。
哈哈,如今可难不倒咱们了,由于咱们使用了CGlib。固然最简单的方式是去修改咱们的方法拦截器,不过这样会使逻辑变得复杂,且
不利于维护。还好CGlib给咱们提供了方法过滤器(CallbackFilter),CallbackFilte能够明确代表,被代理的类中不一样的方法,
被哪一个拦截器所拦截。下面咱们就来作个过滤器用来过滤query方法。
Java代码 
- public class AuthProxyFilter implements CallbackFilter{
- public int accept(Method arg0) {
- if(!"query".equalsIgnoreCase(arg0.getName()))
- return 0;
- return 1;
- }
-
- }
OK,可能你们会对return 0 or 1感到困惑,用到的时候就会讲解,固然下面就会用到了。
咱们在工场中新增一个使用了过滤器的实例生成方法。
Java代码 
- public static TableDAO getAuthInstanceByFilter(AuthProxy authProxy){
- Enhancer en = new Enhancer();
- en.setSuperclass(TableDAO.class);
- en.setCallbacks(new Callback[]{authProxy,NoOp.INSTANCE});
- en.setCallbackFilter(new AuthProxyFilter());
- return (TableDAO)en.create();
- }
看到了吗setCallbacks中定义了所使用的拦截器,其中NoOp.INSTANCE是CGlib所提供的实际是一个没有任何操做的拦截器,
他们是有序的。必定要和CallbackFilter里面的顺序一致。明白了吗?上面return返回的就是返回的顺序。也就是说若是调用query方法就使用NoOp.INSTANCE进行拦截。
如今看一下客户端代码。
Java代码 
- public static void haveAuthByFilter(){
- TableDAO tDao = TableDAOFactory.getAuthInstanceByFilter(new AuthProxy("张三"));
- doMethod(tDao);
-
- tDao = TableDAOFactory.getAuthInstanceByFilter(new AuthProxy("李四"));
- doMethod(tDao);
- }
ok,如今"李四"也可使用query方法了,其余方法仍然没有权限。 哈哈,固然这个代理的实现没有任何侵入性,无需强制让dao去实现接口。