`
zhangwei_david
  • 浏览: 477096 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

CGLIB 之 MethodInterceptor

 
阅读更多

      在学习Spring AOP 的时候我们知道Spring AOP 的实现方式是通过JDK 的动态代理和CGLIB的动态代理实现的,那么什么是CGLIB呢?

       CGLIB其实就是封装了ASM(Java字节码操控框架)了的功能强大,高性能,高质量的Code生成类库。它可以在运行期扩展Java类与实现Java接口。

    我们常见的就是Enhancer类。
它可以动态生成一个子类使方法可以被拦截;处理实现接口,该类还额可以动态生成父类中非final方法的子类,并提供回调用户自定义拦截器的钩子。原生的和普遍被使用的回调类型是MethodInterceptor ,它在AOP方面实现了环绕通知,也就是说你既可以在调用父类方法之前和之后调用自定义的增强代码。此外,你可以在调用父类方法前修改入参,甚至是根本就不调用父类方法。

      虽然,MethodInterceptor 是通用的,足以满足任何拦截需求,但是它往往矫枉过正。为了简单性和性能增加了专门的回调类型 如LazyLoader,经常一个回调在每个拦截器中都没调用,你可以通过CallbackFilter 控制在每个方法上使用哪个回调。

  有这样一个Service 提供了数据的增删改查功能,使用自定义注解标注每个方法被访问时要求的权限

 

/**
 *数据服务类
 * @author zhangwei_david
 * @version $Id: TableDAO.java, v 0.1 2015年1月19日 下午8:16:14 zhangwei_david Exp $
 */
public class MyService {
    @Permission("ADD")
    public void add() {
        System.out.println("create() is running !");
    }

    @Permission({ "ADD", "QUERY", "UPDATE", "QUERY" })
    public void query() {
        System.out.println("query() is running !");
    }

    @Permission({ "UPDATE" })
    public void update() {
        System.out.println("update() is running !");
    }

    @Permission("DELETE")
    public void delete() {
        System.out.println("delete() is running !");
    }
}

 

/**
 *
 * @author zhangwei_david
 * @version $Id: permission.java, v 0.1 2015年1月19日 下午8:58:56 zhangwei_david Exp $
 */
@Documented
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Permission {

    String[] value();

}

 

 

 

/**
 *权限工具类
 * @author zhangwei_david
 * @version $Id: AuthUtils.java, v 0.1 2015年1月19日 下午9:14:07 zhangwei_david Exp $
 */
public class AuthUtils {
    /**
     * 判断当前用户角色是否具有当前方法的访问权限
     *
     * @param method
     * @param role
     * @return
     */
    public static boolean isGrantPermission(Method method, String role) {
        String[] roles = null == method.getAnnotation(Permission.class) ? null : method
            .getAnnotation(Permission.class).value();
        if (roles == null || roles.length == 0) {
            return true;
        }
        for (String string : roles) {
            if (string.equals(role)) {
                return true;
            }
        }
        return false;
    }
}

 

 

 

/**
 *安全代理类
 * @author zhangwei_david
 * @version $Id: AuthProxy.java, v 0.1 2015年1月19日 下午8:20:36 zhangwei_david Exp $
 */
public class AuthProxy implements MethodInterceptor {

    private String role;

    /**
     * @see net.sf.cglib.proxy.MethodInterceptor#intercept(java.lang.Object, java.lang.reflect.Method, java.lang.Object[], net.sf.cglib.proxy.MethodProxy)
     */
    public Object intercept(Object arg0, Method method, Object[] arg2, MethodProxy arg3)
                                                                                        throws Throwable {
        if (AuthUtils.isGrantPermission(method, role)) {
            return arg3.invokeSuper(arg0, arg2);
        }
        System.out.println("expected role is "
                + Arrays.toString(method.getAnnotation(Permission.class).value())
                + " but now is " + role);
        return null;
    }

    public AuthProxy(String role) {
        super();
        this.role = role;
    }

}

 

 

 

 

/**
 *
 * @author zhangwei_david
 * @version $Id: TableDAOFactory.java, v 0.1 2015年1月19日 下午8:16:47 zhangwei_david Exp $
 */
public class DAOFactory {

    public static MyService getInstance(AuthProxy authProxy) {
        Enhancer eh = new Enhancer();
        eh.setSuperclass(MyService.class);
        eh.setCallback(authProxy);
        return (MyService) eh.create();
    }
}

 

 

 

 

/**
 *
 * @author zhangwei_david
 * @version $Id: Client.java, v 0.1 2015年1月19日 下午8:18:18 zhangwei_david Exp $
 */
public class Client {

    /**
     *
     * @param args
     */
    public static void main(String[] args) {
        MyService tableDAO = DAOFactory.getInstance(new AuthProxy("ADD"));
        tableDAO.add();
        tableDAO.delete();
        tableDAO.update();
        tableDAO.query();
    }

}

 结果是:

create() is running !
expected role is [DELETE] but now is ADD
expected role is [UPDATE] but now is ADD
query() is running !

   

发现在AuthUtils判断了一个类是否有权限控制的注解,我们可以想一下如果一个类都没有权限控制为什么还需要进入权限的拦截器中呢?

/**
 *
 * @author zhangwei_david
 * @version $Id: TableDAOFactory.java, v 0.1 2015年1月19日 下午8:16:47 zhangwei_david Exp $
 */
public class DAOFactory {

    public static MyService getInstance(AuthProxy authProxy) {
        Enhancer eh = new Enhancer();
        eh.setSuperclass(MyService.class);
        eh.setCallbacks(new Callback[] { authProxy, NoOp.INSTANCE });
        eh.setCallbackFilter(new PermissionControlleFilter());
        return (MyService) eh.create();
    }
}

 

/**
 *
 * @author zhangwei_david
 * @version $Id: PermissionControlleFilter.java, v 0.1 2015年1月19日 下午10:06:09 zhangwei_david Exp $
 */
public class PermissionControlleFilter implements CallbackFilter {

    /**
     * @see net.sf.cglib.proxy.CallbackFilter#accept(java.lang.reflect.Method)
     */
    public int accept(Method method) {
        if (method.getAnnotation(Permission.class) != null) {
            return 0;
        }
        return 1;
    }

}

 

这样就是表示如果一个方法中没有使用权限注解标注改方法的权限的化就使用第二个拦截器,第二个拦截器

 NoOp.INSTANCE

是CGLIB预定义的一个空个回调。

1
4
分享到:
评论

相关推荐

    cglib的依赖包

    CGlib在其之上进行了封装,使其更易于使用。下面我们将详细探讨CGlib的主要功能和使用方法: 1. **动态代理**:CGlib常被用作JDK动态代理的替代方案,特别是当处理的目标类没有实现接口时。通过创建目标类的子类,...

    cglib及其依赖包

    在Spring AOP中,CGLib通过Enhancer和MethodInterceptor实现了AOP代理。当一个类没有实现接口时,Spring将使用CGLib动态生成该类的子类,并在子类中插入切面代码。这样,每次调用原始类的方法时,都会先执行切面代码...

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

    CGLIB-nodep-2.2.jar包含了CGLIB的所有核心类和接口,如Enhancer、MethodInterceptor等,用于实现动态代理和类的增强。 CGLIB的使用主要集中在以下几个方面: 1. **动态代理**:在Java中,如果我们想要在调用某个...

    cglib_cglib.zip

    CGLib,全称为Code Generation Library,是一个强大的Java代码生成库,广泛用于动态代理、AOP(面向切面编程)等领域。它允许开发者在运行时创建和扩展Java类,而无需直接编写新的源代码或编译步骤。这个压缩包...

    CGLib3.2.5依赖包及源码

    CGLib,全称为Code Generation Library,是一个强大的Java字节码操作库,广泛应用于动态代理、AOP(面向切面编程)以及性能优化等领域。它允许开发者在运行时创建和增强新的类或对象,而无需编写任何Java源代码。...

    cglib-nodep-2.1_3.jar

    【描述】中提到的 "net.sf.cglib.proxy.MethodInterceptor" 是CGlib的核心接口之一。在CGlib中,`MethodInterceptor`扮演着代理对象拦截器的角色,允许开发者在方法调用前后插入自定义逻辑。当通过CGlib创建代理对象...

    cglib2.2.jar

    `Callback`可以是`MethodInterceptor`,在方法调用前后执行自定义逻辑。 3. **字节码生成**:CGLIB通过ASM库生成新的字节码,然后使用Java的反射API来加载这个新生成的类到JVM中。 在实际开发中,选择使用`cglib2.2...

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

    import net.sf.cglib.proxy.MethodInterceptor; import net.sf.cglib.proxy.MethodProxy; public class CGLibExample implements MethodInterceptor { public static void main(String[] args) { Enhancer ...

    cglib动态生成java类

    2. **Callback**:CGLib提供了一系列的回调接口,如`MethodInterceptor`,它允许你在代理对象的方法被调用时执行自定义逻辑。`MethodInterceptor`的`intercept()`方法会在目标方法调用前后执行。 ### 使用示例 ```...

    Cglib的jar文件 Cglib.zip

    import net.sf.cglib.proxy.MethodInterceptor; import net.sf.cglib.proxy.MethodProxy; import java.lang.reflect.Method; public class CglibProxyExample { public static void main(String[] args) { // ...

    cglib所有jar包

    总的来说,CGlib是Java开发中不可或缺的工具之一,它提供了强大的代码生成能力,使得开发者可以更加灵活地扩展和增强已有代码,提高代码的复用性和可维护性。这个"cglib所有jar包"资源对于进行Java开发的程序员来说...

    cglib动态代理相关包

    2. Callback:接口,提供了拦截方法调用的抽象,CGlib中的MethodInterceptor是它的实现。 3. MethodInterceptor:用于拦截和处理方法调用,实现intercept()方法可以自定义代理逻辑。 4. CallbackFilter:可以根据...

    动态代理cglibjar包和源码

    - `net.sf.cglib.proxy.MethodInterceptor`接口定义了拦截器的方法,它的`intercept()`方法会在每次目标方法调用前被调用,我们可以在这里插入额外的业务逻辑。 - `net.sf.cglib.proxy.MethodProxy`是CGLIB用来...

    cglib.jar | asm.jar对应版本

    通过调用`Enhancer.create()`方法,我们可以为指定的类创建一个代理对象,并可以自定义拦截器(`MethodInterceptor`)来控制方法的调用。拦截器中的`intercept()`方法会在目标方法调用前后执行,这样就可以实现AOP...

    CGLIB动态代理jar包

    当你在Enhancer中设置一个实现了MethodInterceptor的实例时,CGLIB会在运行时为每个被代理的方法生成一个代理方法,该方法会调用MethodInterceptor的`intercept`方法。 3. **Callback**:CGLIB的回调机制,它是一个...

    cglib代理模式要使用的相关jar包

    本文将重点介绍使用CGLIB库实现的动态代理。 CGLIB(Code Generation Library)是一个强大的高性能的代码生成库,它在许多AOP(面向切面编程)框架中被广泛应用,如Spring AOP。CGLIB通过字节码技术生成代理类,...

    CGLib代理模式用到的jar包

    CGLib的核心类包括Enhancer、MethodInterceptor和Callback等。 1. Enhancer:这是CGLib的核心类,用于创建代理对象。通过调用它的`create()`方法并传入目标对象,即可得到一个代理对象。这个代理对象在运行时实际上...

    cglib依赖功四个jar+java实例.rar

    2. 配置回调方法:使用CGLIB的MethodInterceptor接口,实现intercept()方法。这个方法会在目标方法调用前、后以及异常处理时被调用,你可以在此处添加自定义的行为。 3. 生成代理对象:使用Enhancer.create()方法,...

    Cglib所需要的jar包

    import net.sf.cglib.proxy.MethodInterceptor; import net.sf.cglib.proxy.MethodProxy; import java.lang.reflect.Method; public class CglibProxyExample { public static void main(String[] args) { ...

Global site tag (gtag.js) - Google Analytics