美文网首页
cglib动态代理的使用

cglib动态代理的使用

作者: sunpy | 来源:发表于2018-08-01 17:58 被阅读15次
    风景.jpg

    介绍

    cglib是在运行期扩展java类与实现java接口。cglib包的底层是通过使用一个小而快的字节码处理框架ASM,来转换字节码并生成新的类。ASM本身是操作字节码,jvm不管你是通过编译器将java代码转换为字节码还是直接通过ASM生成字节码,只要字节码文件符合jvm的解析结构即可。cglib在spring Aop中被经常使用。

    入门例子

    public class OperationClass {
    
        public void printData(String data) {
            System.out.println(data);
        }
        
        public void delData(String id) {
            System.out.println("删除指定ID = " + id + "的数据!");
        }
    }
    
    public class OperationProxyClass implements MethodInterceptor {
    
        @Override
        public Object intercept(Object obj, Method method, 
                        Object[] args, MethodProxy proxy) throws Throwable {
            proxy.invokeSuper(obj, args);
            return obj;
        }
    }
    
    public class CglibTest {
    
        public Object getProxyInstance() {
            Enhancer enhancer = new Enhancer();
            enhancer.setSuperclass(OperationClass.class);
            enhancer.setCallback(new OperationProxyClass());
            return enhancer.create();
        }
        
        public static void main(String[] args) {
            OperationClass oc = new OperationClass();
            OperationClass ocProxy = (OperationClass) new CglibTest().getProxyInstance();
            ocProxy.printData("test cglib");
            ocProxy.delData("123456");
            System.out.println(oc.getClass());
            System.out.println(ocProxy.getClass());
        }
    }
    

    结果:


    2.png

    解释:
    intercept方法参数
    Object obj:表示要进行增强的对象
    Method method:表示拦截的方法
    Object[] args:基本数据类型需要传入其包装类型
    MethodProxy proxy:表示对方法的代理
    注意:我们设置了目标类作为代理类的父类(setSuperclass),在cglib中目标类的创建不是我们自己手工去创建,而是cglib通过反射动态去创建的。

    cglib中拦截器的使用

    public class OperationProxy2Class implements MethodInterceptor {
    
        @Override
        public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
            
            return obj;
        }
    }
    
    public class OperationClassFilter implements CallbackFilter{
    
        @Override
        public int accept(Method method) {
            if (method.getName().equals("printData")) {
                return 1;
            } 
            
            return 2;
        }
    }
    
    public class CglibTest {
    
        public Object getProxyInstance() {
            
            Enhancer enhancer = new Enhancer();
            enhancer.setSuperclass(OperationClass.class);
            enhancer.setCallbacks(new Callback[]{new OperationProxyClass(), new OperationProxy2Class(), NoOp.INSTANCE});
            enhancer.setCallbackFilter(new OperationClassFilter());
            return enhancer.create();
        }
        
        public static void main(String[] args) {
            OperationClass oc = new OperationClass();
            OperationClass ocProxy = (OperationClass) new CglibTest().getProxyInstance();
            ocProxy.printData("test cglib");
            ocProxy.delData("123456");
            System.out.println(oc.getClass());
            System.out.println(ocProxy.getClass());
        }
    }
    
    3.png

    注意:
    OperationClassFilter 中的返回值代表使用Callbacks指定的数组下标对应的拦截器。
    上面Callbacks定义的三种拦截器:
    ① 拦截器拦截的方法一定会执行,OperationProxyClass。
    ② 该拦截器拦截的方法不会执行,OperationProxy2Class。
    ③ 默认拦截器,什么拦截都不做,NoOp.INSTANCE。

    相关文章

      网友评论

          本文标题:cglib动态代理的使用

          本文链接:https://www.haomeiwen.com/subject/gwylvftx.html