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

前言

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

使用

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

	<dependencies>
        <dependency>
            <groupId>cglib</groupId>
            <artifactId>cglib</artifactId>
            <version>3.2.12</version>
        </dependency>
    </dependencies>

拦截类说明和创建
创建一个拦截器类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。从这里可以看出对应的实现不是通过反射而是通过继承。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值