cglib 动态代理基础篇

cglib 动态代理基础篇

CGlib是什么? 
CGlib是一个强大的,高性能,高质量的Code生成类库。它可以在运行期扩展Java类与实现Java接口。 
下面我们将通过一个具体的事例来看一下CGlib体验一下CGlib。 
cglib-nodep-2.2.2.jar

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实例。 

public class TableDAOFactory {
    private static TableDAO tDao = new TableDAO();
    public static TableDAO getInstance(){
        return tDao;
    }
}

接下来我们创建客户端,用来调用CRUD方法。

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。 
我们只需新增一个权限验证的方法拦截器。 

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 TableDAO getAuthInstance(AuthProxy authProxy){
    Enhancer en = new Enhancer();
    //进行代理
    en.setSuperclass(TableDAO.class);
    en.setCallback(authProxy);
    //生成代理实例
    return (TableDAO)en.create();
}

OK,"张三"的正常执行,"李四"的没有执行。 
看到了吗?简单的aop就这样实现了 
难道就这样结束了么? 
3. Boss又来训话了,不行不行,现在除了"张三"其他人都用不了了,现在不可以这样。他们都来向我反映了,必须使用开放查询功能。 
哈哈,现在可难不倒我们了,因为我们使用了CGlib。当然最简单的方式是去修改我们的方法拦截器,不过这样会使逻辑变得复杂,且 
不利于维护。还好CGlib给我们提供了方法过滤器(CallbackFilter),CallbackFilte可以明确表明,被代理的类中不同的方法, 
被哪个拦截器所拦截。下面我们就来做个过滤器用来过滤query方法。 

public class AuthProxyFilter implements CallbackFilter{
    public int accept(Method arg0) {
        if(!"query".equalsIgnoreCase(arg0.getName()))
            return 0;
        return 1;
    }

}

OK,可能大家会对return 0 or 1感到困惑,用到的时候就会讲解,当然下面就会用到了。 
我们在工场中新增一个使用了过滤器的实例生成方法。 

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();
}
原文地址:https://www.cnblogs.com/daxin/p/3352901.html