栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

cglib动态代理使用和源码分析心得

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

cglib动态代理使用和源码分析心得

前言

前几天使用公司项目,分析到某个代码接口实现类扫包增强型执行,就是使用的cglib动态代理模式,用来实现对日志打印、分布式锁、事务和异步线程池执行的增强。这里的底层原理是怎样,我下文进行表述。

使用

maven依赖引入
创建一个maven项目,pom.xml文件引入如下的依赖。

	
        
            cglib
            cglib
            3.2.12
        
    

拦截类说明和创建
创建一个拦截器类CglibMethodInterceptor,实现接口net.sf.cglib.proxy.MethodInterceptor,对应的方法如下:

public class CglibMethodInterceptor implements MethodInterceptor {

    @Override
    public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
        System.out.println("<<<<<日志收集开始...>>>>>>>");
        Object reuslt = proxy.invokeSuper(obj, args);
        System.out.println("<<<<<日志收集结束...>>>>>>>");
        return reuslt;
    }
}

proxy为代理类,obj为代理对象,args为目标参数。proxy.invokeSuper(obj,args)为执行代理对象的目标方法。method为目标方法。

如果需要使用代理,则编写如下的方法:

public class TestProxy {
    public static void main(String[] args) {
        //System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "E:\code");
        CglibMethodInterceptor cglibMethodInterceptor = new CglibMethodInterceptor();
        Enhancer enhancer = new Enhancer();
// 设置代理类的父类
        enhancer.setSuperclass(HelloServiceImpl.class);
// 设置回调对象
        enhancer.setCallback(cglibMethodInterceptor);
// 创建代理对象
        HelloService orderService = (HelloServiceImpl) enhancer.create();
        orderService.hello();
    }
}

Enhancer这里要加入回调拦截器,就是通过setCallback方法进行的,被代理类在setSuperclass来传入的。代理对象通过enhancer#create()方法来创建的。这里可以看到cglib动态代理是通过继承法来进行代理的。那这里底层原理是怎样的,下一节可以展示的。

cglib动态代理原理


如图所示,cglib动态代理生成三个类,第一个的父类才是被代理的类,另外两个是cglib包的enhancer和fastClass的子类。当调用被代理类的方法hello时,走如下的代码:

public final void hello() {
        MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
        if (var10000 == null) {
            CGLIB$BIND_CALLBACKS(this);
            var10000 = this.CGLIB$CALLBACK_0;
        }

        if (var10000 != null) {
            var10000.intercept(this, CGLIB$hello$0$Method, CGLIB$emptyArgs, CGLIB$hello$0$Proxy);
        } else {
            super.hello();
        }
    }

这里MethodInterceptor 是上面的实现子类,它为null则直接执行被代理类对应的方法,如果不为空则执行对应的intercept方法。而fastClass如何调用对应的代理类呢?那请看下面的代码:

 public Object invokeSuper(Object obj, Object[] args) throws Throwable {
        try {
            init();
            FastClassInfo fci = fastClassInfo;
            return fci.f2.invoke(fci.i2, obj, args);
        } catch (InvocationTargetException e) {
            throw e.getTargetException();
        }
    }
 private static class FastClassInfo
    {
        FastClass f1;
        FastClass f2;
        int i1;
        int i2;
    }

Fastclass类的作用是创建索引机制。他的子类就是上面的第二个,对应生成代码如下:

public int getIndex(Class[] var1) {
        switch(var1.length) {
        case 0:
            return 0;
        default:
            return -1;
        }
    }

    public Object invoke(int var1, Object var2, Object[] var3) throws InvocationTargetException {
        HelloServiceImpl var10000 = (HelloServiceImpl)var2;
        int var10001 = var1;

        try {
            switch(var10001) {
            case 0:
                var10000.hello();
                return null;
            case 1:
                return new Boolean(var10000.equals(var3[0]));
            case 2:
                return var10000.toString();
            case 3:
                return new Integer(var10000.hashCode());
            }
        } catch (Throwable var4) {
            throw new InvocationTargetException(var4);
        }

        throw new IllegalArgumentException("Cannot find matching method/constructor");
    }

如果index为0,则执行被代理类的hello。从这里可以看出对应的实现不是通过反射而是通过继承。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/695248.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号