`

CGLIB技术详解

阅读更多

一、CGLIB简介

 

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

 

二、准备工作

 

    要使用cglib那么有两个jar包是必不可少的,一个是asm.jar,一个是cglib.jar包,在本文中有提供下载。

 

三、CGLIB应用

 

    首先我们模拟一个信息管理的场景,然后再来介绍cglib的应用

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

 

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

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--工厂类

public class InfoManagerFactory {
    private static InfoManager manger = new InfoManager();
    /**
     * 创建原始的InfoManager
     * 
     * @return
     */
    public static InfoManager getInstance() {
        return manger;
    }
}

 

    client.java--供客户端调用

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--权限校验代理类

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--代码变动如下:

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--代码修改如下

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端中已经加上了权限校验。

 

    3、由于query功能用户maurice才能使用,招来其他用户的强烈的抱怨,所以权限再次变更,只有create,update,delete,才需要权限保护,query任何人都可以使用。

    怎么办?采用AuthProxy,使得InfoManager中的所有方法都被代理,加上了权限的判断。当然,最容易想到的办法,就是在AuthProxy的intercept的方法中再做下判断,如果代理的method是query,不需要权限验证。这么做,可以,但是一旦逻辑比较复杂的时候,intercept这个方法要做的事情会很多,逻辑会异常的复杂。
    幸好,cglib还提供了CallbackFilter。使用CallbackFilter,可以明确表明,被代理的类(InfoManager)中不同的方法,被哪个拦截器(interceptor)拦截。

 

    AuthProxyFilter.java

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)

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

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等框架中,被大量的使用。

 

    文章出处:http://www.blogjava.net/stone2083/archive/2008/03/16/186615.html

分享到:
评论

相关推荐

    cglib.jar/cglib-nodep.jar免费下载

    **CGLib库详解** CGLib,全称Code Generation Library,是一个强大的高性能的代码生成库,它在Java世界中被广泛使用,特别是在动态代理和AOP(面向切面编程)领域。这个库允许开发者在运行时动态创建类或者增强已有...

    cglib2.2jar包

    **CGLIB2.2 Jar包详解** CGLIB(Code Generation Library)是一个强大的高性能的代码生成库,它被广泛应用于Java世界中的动态代理和字节码操作。CGLIB是基于ASM库来实现的,ASM是一个底层的Java字节码操控和分析...

    cglib-3.1源码

    **CGLIB 3.1 源码详解** CGLIB(Code Generation Library)是一个强大的、高性能的代码生成库,它在Java运行时能够动态地生成子类,主要用于为Java对象提供代理或者扩展功能。CGLIB是许多Java框架的基础,如Spring ...

    cglib的依赖包

    它通过字节码技术为类创建子类,从而实现对目标类的功能增强。在Java中,由于无法直接继承final类或者重写final方法,CGlib提供了一种解决方案,使得我们能够在运行时动态地扩展或修改类的行为。 CGlib的核心是ASM...

    Java动态代理机制详解(JDK 和CGLIB,Javassist,ASM)

    CGLIB通过字节码技术生成一个子类来实现代理,因此对类的代理效率较高。CGLIB使用ASM库来生成和转换字节码,其核心类是`net.sf.cglib.proxy.Enhancer`,我们可以设置Enhancer的callback来实现方法拦截。 **...

    com.springsource.net.sf.cglib.7z

    《Spring框架中的CGLIB库详解》 在Java开发领域,Spring框架以其强大的功能和灵活性深受开发者喜爱。在Spring框架的众多组件中,CGLIB(Code Generation Library)扮演着重要角色,尤其在面向切面编程(AOP)中不可...

    Java动态代理详解; CGLib实现动态代理1

    Java 动态代理详解与 CGLib 实现 在 Java 中,代理模式是一种设计模式,它允许我们在不修改原有对象的基础上,为对象增加额外的功能。代理模式的核心在于代理类(Proxy)作为真实对象(RealSubject)的替代品,提供...

    Java JDK代理、CGLIB、AspectJ代理分析比较

    ### Java代理技术详解:JDK代理、CGLIB与AspectJ #### 一、代理模式简介 代理模式是一种常见的设计模式,在《Design Patterns in Java》一书中对其有明确的定义:“代理模式为一个对象提供一个代理,以控制对该...

    Spring框架系列(11) - Spring AOP实现原理详解之Cglib代理实现.doc

    在这个例子中,当我们调用`targetProxy.doSomething()`时,实际执行的是Cglib生成的子类中的方法,这个方法会在调用`doSomething()`前后执行`MyAdvice`中的`intercept`方法,这就是Cglib代理的工作原理。 总的来说...

    Java 动态代理详解(学习资料)

    新的 UserService 实例 = new UserServiceImpl(); UserService proxyUserService = new UserServiceProxy(userServiceImpl);...了解和掌握动态代理技术对于深入理解 Java 并应用于实际项目开发有着重要的意义。

    spring框架,技术详解及使用指导.zip

    2. **AOP代理**:Spring支持JDK动态代理和CGLIB代理,用于实现AOP功能,拦截并处理方法调用。 3. **事务管理**:Spring提供声明式和编程式两种事务管理方式,简化了事务处理。 四、使用指南 1. **环境准备**:安装...

    Java动态代理方法详解.docx

    CGLIB代理通过字节码技术生成子类来实现代理,因此目标类无需实现接口。 四、应用场景 1. 框架集成:MyBatis、Spring等框架广泛使用动态代理来实现AOP(面向切面编程),如事务管理、日志记录等。 2. 缓存:在调用...

    Spring MVC 框架搭建及详解

    如描述中所示,Spring 2.5.6版本需要包括spring.jar、spring-webmvc.jar、commons-logging.jar和cglib-nodep-2.1_3.jar等。同时,如果你打算结合Hibernate进行持久层操作,还需要引入Hibernate的相关jar包,如...

    hibernate2开发包详解

    - **描述**:CGLIB库是基于ASM字节码技术实现的一个高性能、动态代理库。 - **作用**:Hibernate利用CGLIB来实现PO(Plain Old Java Object,普通老式Java对象)字节码的动态生成,用于生成代理类或实现对象状态的...

    cglibfull包

    例如,在Spring AOP框架中,CGLib就是用来生成代理对象的技术之一。 CGLib的工作原理是通过ASM库动态生成字节码,然后利用Java的ClassLoader将这些字节码转换为运行时的类。这个过程通常包括以下步骤: 1. 创建...

    Java动态代理两种实现方式

    Java动态代理技术是Java编程中一个非常重要的特性,它允许我们在运行时动态创建具有特定行为的对象。这种技术常用于AOP(面向切面编程)和框架中,如Spring AOP,用于实现方法拦截、事务管理等功能。Java提供了两种...

    java_dongruan.rar_东软

    【Java动态代理技术详解】 Java动态代理是Java提供的一种在运行时创建代理对象的技术,它允许我们创建代表其他对象的对象,这些代理对象可以在调用实际方法之前和之后执行额外的操作。这种技术对于实现AOP(面向切...

    Hibernate包作用详解.docx

    Hibernate是一款强大的Java持久化框架,它的主要作用是简化数据库操作,通过对象关系映射(ORM)技术将数据库的记录映射为Java对象,使得开发者能够使用面向对象的方式来处理数据库交互,而无需直接编写SQL语句。...

Global site tag (gtag.js) - Google Analytics