CGlib简单介绍

系统 1557 0

CGlib概述:
cglib( Code Generation Library )是一个强大的,高性能,高质量的Code生成类库。它可以在运行期扩展Java类与实现Java接口。
cglib封装了asm,可以在运行期动态生成新的class。
cglib用于AOP,jdk中的proxy必须基于接口,cglib却没有这个限制。

CGlib应用:
以一个实例在简单介绍下cglib的应用。
我们模拟一个虚拟的场景,关于信息的管理。

1)原始需求是任何人可以操作信息的create,update,delete,query操作。


InfoManager.java --封装对信息的操作

<!-- <br /> <br /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br /> http://www.CodeHighlighter.com/<br /> <br /> -->
public   class  InfoManager {
    
//  模拟查询操作
     public   void  query() {
        System.out.println(
" query " );
    }
    
//  模拟创建操作
     public   void  create() {
        System.out.println(
" create " );
    }
    
//  模拟更新操作
     public   void  update() {
        System.out.println(
" update " );
    }
    
//  模拟删除操作
     public   void  delete() {
        System.out.println(
" delete " );
    }
}

 

InfoManagerFactory.java --工厂类

<!-- <br /> <br /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br /> http://www.CodeHighlighter.com/<br /> <br /> -->
public   class  InfoManagerFactory {
    
private   static  InfoManager manger  =   new  InfoManager();
    
/**
     * 创建原始的InfoManager
     * 
     * 
@return
     
*/
    
public   static  InfoManager getInstance() {
        
return  manger;
    }
}

 

client.java --供客户端调用

<!-- <br /> <br /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br /> http://www.CodeHighlighter.com/<br /> <br /> -->
public   class  Client {

    
public   static   void  main(String[] args) {
        Client c 
=   new  Client();
        c.anyonecanManager();
    }

    
/**
     * 模拟:没有任何权限要求,任何人都可以操作
     
*/
    
public   void  anyonecanManager() {
        System.out.println(
" any one can do manager " );
        InfoManager manager 
=  InfoManagerFactory.getInstance();
        doCRUD(manager);
        separatorLine();
    }

    
/**
     * 对Info做增加/更新/删除/查询操作
     * 
     * 
@param  manager
     
*/
    
private   void  doCRUD(InfoManager manager) {
        manager.create();
        manager.update();
        manager.delete();
        manager.query();
    }

    
/**
     * 加一个分隔行,用于区分
     
*/
    
private   void  separatorLine() {
        System.out.println(
" ################################ " );
    }

}

至此,没有涉及到cglib的内容,因为需求太简单了,但是接下来,需求发生了改变,要求:

2)只有一个叫“maurice”的用户登录,才允许对信息进行create,update,delete,query的操作。
怎么办?难道在每个方法前,都加上一个权限判断吗?这样重复逻辑太多了,于是乎想到了Proxy(代理模式),但是原先的InfoManager也没有实现接口,不能采用jdk的proxy。那么cglib在这边就要隆重登场。
一旦使用cgblig,只需要添加一个MethodInterceptor的类以及修改factory代码就可以实现这个需求。

 

AuthProxy.java --权限校验代理类

<!-- <br /> <br /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br /> http://www.CodeHighlighter.com/<br /> <br /> -->
public   class  AuthProxy  implements  MethodInterceptor {

    
private  String name;  //  会员登录名

    
public  AuthProxy(String name) {
        
this .name  =  name;
    }

    
/**
     * 权限校验,如果会员名为:maurice,则有权限做操作,否则提示没有权限
     
*/
    @Override
    
public  Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy)  throws  Throwable {
        
if  ( ! " maurice " .equals( this .name)) {
            System.out.println(
" AuthProxy:you have no permits to do manager! " );
            
return   null ;
        }
        
return  proxy.invokeSuper(obj, args);
    }

    
public  String getName() {
        
return  name;
    }

    
public   void  setName(String name) {
        
this .name  =  name;
    }

}

 

InfoManagerFactory.java --代码变动如下:

<!-- <br /> <br /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br /> http://www.CodeHighlighter.com/<br /> <br /> -->
public   class  InfoManagerFactory {

    
/**
     * 创建带有权限检验的InfoManager
     * 
     * 
@param  auth
     * 
@return
     
*/
    
public   static  InfoManager getAuthInstance(AuthProxy auth) {
        Enhancer enhancer 
=   new  Enhancer();
        enhancer.setSuperclass(InfoManager.
class );
        enhancer.setCallback(auth);
        
return  (InfoManager) enhancer.create();
    }

    
}

 

client.java --代码修改如下

<!-- <br /> <br /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br /> http://www.CodeHighlighter.com/<br /> <br /> -->
public   class  Client {

    
public   static   void  main(String[] args) {
        Client c 
=   new  Client();
        c.haveNoAuthManager();
        c.haveAuthManager();
    }

    
/**
     * 模拟:登录会员没有权限
     
*/
    
public   void  haveNoAuthManager() {
        System.out.println(
" the loginer's name is not maurice,so have no permits do manager " );
        InfoManager noAuthManager 
=  InfoManagerFactory.getAuthInstance( new  AuthProxy( " maurice1 " ));
        doCRUD(noAuthManager);
        separatorLine();
    }

    
/**
     * 模拟:登录会员有权限
     
*/
    
public   void  haveAuthManager() {
        System.out.println(
" the loginer's name is maurice,so have permits do manager " );
        InfoManager authManager 
=  InfoManagerFactory.getAuthInstance( new  AuthProxy( " maurice " ));
        doCRUD(authManager);
        separatorLine();
    }

    
/**
     * 对Info做增加/更新/删除/查询操作
     * 
     * 
@param  manager
     
*/
    
private   void  doCRUD(InfoManager manager) {
        manager.create();
        manager.update();
        manager.delete();
        manager.query();
    }

    
/**
     * 加一个分隔行,用于区分
     
*/
    
private   void  separatorLine() {
        System.out.println(
" ################################ " );
    }

}

执行下代码,发现这时client端中已经加上了权限校验。

到这里,参照上面的代码,就可以使用cglib带来的aop功能了。但是为了更多介绍下cglib的功能,模拟需求再次发生变化:

3)由于query功能用户maurice才能使用,招来其他用户的强烈的抱怨,所以权限再次变更,只有create,update,delete,才需要权限保护,query任何人都可以使用。
怎么办?采用AuthProxy,使得InfoManager中的所有方法都被代理,加上了权限的判断。当然,最容易想到的办法,就是在 AuthProxy的intercept的方法中再做下判断,如果代理的method是query,不需要权限验证。这么做,可以,但是一旦逻辑比较复杂 的时候,intercept这个方法要做的事情会很多,逻辑会异常的复杂。
幸好,cglib还提供了CallbackFilter。使用CallbackFilter,可以明确表明,被代理的类(InfoManager)中不同的方法,被哪个拦截器(interceptor)拦截。

 

AuthProxyFilter.java

<!-- <br /> <br /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br /> http://www.CodeHighlighter.com/<br /> <br /> -->
public   class  AuthProxyFilter  implements  CallbackFilter {

    
private   static   final   int  AUTH_NEED      =   0 ;
    
private   static   final   int  AUTH_NOT_NEED  =   1 ;

    
/**
     * <pre>
     * 选择使用的proxy
     * 如果调用query函数,则使用第二个proxy
     * 否则,使用第一个proxy
     * </pre>
     
*/
    @Override
    
public   int  accept(Method method) {
        
if  ( " query " .equals(method.getName())) {
            
return  AUTH_NOT_NEED;
        }
        
return  AUTH_NEED;
    }

}

这段代码什么意思?其中的accept方法的意思是说,如果代理的方法是query(),那么使用第二个拦截器去拦截,如果代理的方法不是 query(),那么使用第一个拦截器去拦截。所以我们只要再写一个拦截器,不做权限校验就行了。(其实,cglib中的NoOp.INSTANCE就是 一个空的拦截器,只要配置上这个就可以了。)

 

InfoManagerFactory.java --代码修改如下:(配置不同的拦截器和filter)

<!-- <br /> <br /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br /> http://www.CodeHighlighter.com/<br /> <br /> -->
public   class  InfoManagerFactory {

    
/**
     * 创建不同权限要求的InfoManager
     * 
     * 
@param  auth
     * 
@return
     
*/
    
public   static  InfoManager getSelectivityAuthInstance(AuthProxy auth) {
        Enhancer enhancer 
=   new  Enhancer();
        enhancer.setSuperclass(InfoManager.
class );
        enhancer.setCallbacks(
new  Callback[] { auth, NoOp.INSTANCE });
        enhancer.setCallbackFilter(
new  AuthProxyFilter());
        
return  (InfoManager) enhancer.create();
    }

}

记住:setCallbacks中的拦截器(interceptor)的顺序,一定要和 CallbackFilter里面指定的顺序一致!!切忌。

Client.java

<!-- <br /> <br /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br /> http://www.CodeHighlighter.com/<br /> <br /> --> public   class  Client {

    
public   static   void  main(String[] args) {
        Client c 
=   new  Client();
        c.selectivityAuthManager();
    }
    
    
/**
     * 模拟:没有权限的会员,可以作查询操作
     
*/
    
public   void  selectivityAuthManager() {
        System.out.println(
" the loginer's name is not maurice,so have no permits do manager except do query operator " );
        InfoManager authManager 
=  InfoManagerFactory.getSelectivityAuthInstance( new  AuthProxy( " maurice1 " ));
        doCRUD(authManager);
        separatorLine();
    }

    
/**
     * 对Info做增加/更新/删除/查询操作
     * 
     * 
@param  manager
     
*/
    
private   void  doCRUD(InfoManager manager) {
        manager.create();
        manager.update();
        manager.delete();
        manager.query();
    }

    
/**
     * 加一个分隔行,用于区分
     
*/
    
private   void  separatorLine() {
        System.out.println(
" ################################ " );
    }

}

此时,对于query的权限校验已经被去掉了。


通过一个模拟需求,简单介绍了cglib aop功能的使用。
CGlib应用非常广,在spring,hibernate等框架中,被大量的使用。

CGlib简单介绍


更多文章、技术交流、商务合作、联系博主

微信扫码或搜索:z360901061

微信扫一扫加我为好友

QQ号联系: 360901061

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描下面二维码支持博主2元、5元、10元、20元等您想捐的金额吧,狠狠点击下面给点支持吧,站长非常感激您!手机微信长按不能支付解决办法:请将微信支付二维码保存到相册,切换到微信,然后点击微信右上角扫一扫功能,选择支付二维码完成支付。

【本文对您有帮助就好】

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描上面二维码支持博主2元、5元、10元、自定义金额等您想捐的金额吧,站长会非常 感谢您的哦!!!

发表我的评论
最新评论 总共0条评论