`
yunmanfan
  • 浏览: 94035 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

05-11 (转)CGlib简单介绍

阅读更多

原文:http://www.blogjava.net/stone2083/archive/2008/03/16/186615.html

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--封装对信息的操作

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

同样是InfoManager,为什么这时能多了权限的判断呢?Factory中enhancer.create()返回的到底是什么对象呢?这个疑问将在第三部分CGlib中解释。

这边的代码,其实是介绍了cglib中的enhancer功能.

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

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

CGlib原理:

cglib神奇吗?其实一旦了解cglib enhancer的原理,一切就真相大白了。

刚才在第二部分中,有个疑问:enhancer.create()到底返回了什么对象?

其实在刚才的例子中,cglib在代码运行期,动态生成了InfoManager的子类,并且根据CallbackFilter的accept方法,覆写了InfoManager中的所有方法--去执行相应的MethodInterceptor的intercept方法

分享到:
评论
2 楼 燕子~~ 2008-07-02  
如果我是用配置文件的方法呢,我想对一个类中的某些方法拦截,
1 楼 燕子~~ 2008-07-02  
似乎这下面代码有问题啊,,我在编写这句时,总是报错enhancer.setCallbacks(new Callback[] { auth, NoOp.INSTANCE }); 请问你加了cglib的几个包啊?谢谢

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();

     }

}

相关推荐

    强势推送cglib-full-2.0及cglib-full-2.0.2

    CGLib,全称为Code Generation Library,是一个强大的Java字节码操控和动态代理框架。它主要通过ASM库在运行期动态生成新的类和方法,广泛应用于许多框架和库中,如Spring AOP、Hibernate等,以提供对目标类的增强或...

    CGLIB需要的asm-2.2.3.jar和cglib-nodep-2.2.jar

    CGLIB,全称为Code Generation Library,是一个强大的高性能的代码生成库,被广泛应用于Java世界,尤其是Spring框架中。它允许程序在运行时动态地创建Java对象并扩展已有类的功能。CGLIB是通过字节码技术实现的,而...

    开发工具 cglib-3.2.4

    开发工具 cglib-3.2.4开发工具 cglib-3.2.4开发工具 cglib-3.2.4开发工具 cglib-3.2.4开发工具 cglib-3.2.4开发工具 cglib-3.2.4开发工具 cglib-3.2.4开发工具 cglib-3.2.4开发工具 cglib-3.2.4开发工具 cglib-3.2.4...

    Spring学习笔记(14)----使用CGLIB实现AOP功能

    在本篇Spring学习笔记中,我们将探讨如何使用CGLIB库来实现AOP功能。 CGLIB(Code Generation Library)是一个强大的高性能的代码生成库,它被广泛用于动态代理和运行时织入AOP切面。在Spring中,如果目标类没有...

    spring-cglib-repack-3.2.0.jar和spring-objenesis-repack-2.1.jar

    在这个问题中,我们遇到了两个关键的jar包:`spring-cglib-repack-3.2.0.jar`和`spring-objenesis-repack-2.1.jar`。这两个jar包对于理解Spring框架的工作原理以及它们在实际应用中的作用至关重要。 首先,`spring-...

    cglib-nodep-2.2.3.jar

    cglib-nodep-2.2.3.jar cglig 库文件

    开发JAR包-ant asm cglib

    解压文件即可: ant-1.6.5.jar antlr-2.7.6.jar asm-2.2.3.jar asm-commons-2.2.3.jar asm-util-2.2.3.jar cglib-nodep-2.1_3.jar

    spring-cglib-repack-3.0.jar

    org.springframework.asm.AnnotationVisitor org.springframework.cglib.core.ClassGenerator

    spring-cglib-repack-3.2.5.jar,spring-objenesis-repack-2.6.ja及ck-2.5.1.jar

    "spring-cglib-repack-3.2.5.jar"、"spring-objenesis-repack-2.6.jar"和"spring-objenesis-repack-2.5.1.jar"这三个文件是Spring源码阅读环境中常用的依赖包,它们各自承担着不同的功能。 首先,我们来看"CGLIB"...

    JavaEE源代码 cglib-2.1.3

    JavaEE源代码 cglib-2.1.3JavaEE源代码 cglib-2.1.3JavaEE源代码 cglib-2.1.3JavaEE源代码 cglib-2.1.3JavaEE源代码 cglib-2.1.3JavaEE源代码 cglib-2.1.3JavaEE源代码 cglib-2.1.3JavaEE源代码 cglib-2.1.3JavaEE源...

    spring-cglib-repack-3.2.6.jar和spring-objenesis-repack-2.6.jar

    在提供的文件中,我们看到了两个与Spring相关的库:`spring-cglib-repack-3.2.6.jar` 和 `spring-objenesis-repack-2.6.jar`。这两个库都是Spring框架的重要组成部分,用于解决特定的编程问题。 首先,让我们来了解...

    spring-cglib-repack-3.2.4.jar和spring-objenesis-repack-2.5.1.jar

    在深入理解`spring-cglib-repack-3.2.4.jar`和`spring-objenesis-repack-2.5.1.jar`这两个jar包之前,我们先来了解一下Spring框架的核心概念。 Spring框架的核心包括依赖注入(Dependency Injection,DI)和面向切...

    spring-cglib-repack-3.2.5.jar和spring-objenesis-repack-2.6.jar

    标题中的"spring-cglib-repack-3.2.5.jar"和"spring-objenesis-repack-2.6.jar"是两个与Spring框架相关的库文件,它们主要用于Spring框架的内部实现,尤其是针对Java对象的创建和代理机制。下面将详细解释这两个库的...

    hibernate-cglib-repack-2.1_3.jar.zip

    《深入理解Hibernate-CGLIB-2.1_3在Java开发中的应用》 在Java开发领域,Hibernate作为一款强大的对象关系映射(ORM)框架,极大地简化了数据库操作。而CGLIB则是一个代码生成库,它允许开发者在运行时动态创建子类...

    spring-cglib-repack-3.2.6.jar,spring-objenesis-repack-2.6.jarspring-cglib-repack

    在给定的标题和描述中,提到了两个关键的jar包:`spring-cglib-repack-3.2.6.jar` 和 `spring-objenesis-repack-2.6.jar`。这两个文件对于理解Spring框架的内部机制以及如何在IDEA中构建Spring源码至关重要。 首先...

    spring-cglib-repack-3.2.5.jar,spring-objenesis-repack-2.6.jar

    在测试环境中,Objenesis可以帮助快速创建对象,尤其是那些带有复杂初始化逻辑的类,使得测试更加简单高效。Spring框架提供了丰富的测试支持,包括单元测试和集成测试,Objenesis的集成使得这些测试更加灵活。 这...

    spring-cglib spring-objenesis

    spring-cglib-repack-3.2.6.jar 文件大小:313502 字节 修改时间:2018年8月26日 09:12:09 MD5 :1F3A42309EC16632954291B584778432 SHA1 :7A9601D36541798180C2AFC4DA34A78237F5C0AA CRC32 :675C7EB7 spring-...

    3.2版本Spring源码需要源码所需要的jar:spring-asm-repack-5.0.4.jar,spring-cglib-repack-3.1.jar

    Spring使用CGLIB作为默认的AOP代理机制,当目标对象不能或不适合使用Java接口时,CGLIB就会生成一个子类来代理目标对象。spring-cglib-repack-3.1.jar是CGLIB的一个打包版本,包含了必要的类和资源,专为Spring框架...

    cglib-2.2.2.jar

    cglib-2.2.2.jar

    spring-cglib-repack-3.1.jar,spring-objenesis-repack-2.1.jar

    本文将详细介绍这两个jar包以及它们与Spring框架的关系。 首先,"spring-cglib-repack-3.1.jar"是一个针对CGLIB(Code Generation Library)的打包版本,用于在运行时动态创建Java类的子类。CGLIB是一个强大的代码...

Global site tag (gtag.js) - Google Analytics