前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >cglib动态代理和retrofit

cglib动态代理和retrofit

作者头像
提莫队长
发布2020-06-02 15:25:40
4600
发布2020-06-02 15:25:40
举报
文章被收录于专栏:刘晓杰

1.cglib介绍

代理提供了一个可扩展的机制来控制被代理对象的访问,其实说白了就是在对象访问的时候加了一层封装。jdk动态代理使用起来非常简单,但是有个明显的缺点:需要目标对象实现一个或多个接口。假如你想代理没有接口的类呢?可以使用CGLIB库。 cglib有个最重要的接口MethodInterceptor,这个接口只有一个方法:

代码语言:javascript
复制
public Object intercept(Object object, java.lang.reflect.Method method, Object[] args, MethodProxy proxy) throws Throwable;

MethodInterceptor.intercept方法的第一个参数是代理对象,第二个、第三个参数分别是被拦截的方法和方法的参数。 如果想调用被代理对象的原始方法,可以通过使用Method对象来反射调用,或者使用MethodProxy对象。我们通常使用MethodProxy因为它更快。 在intercept方法中,自定义代码可以在原始方法调用前或调用后注入。

2.简单Demo

(记得添加依赖 cglib的github地址有)

  • 1.实现一个业务类,注意,这个业务类并没有实现任何接口
代码语言:javascript
复制
public class RetrofitService {
    public void loadData(String params) {
        System.out.println("RetrofitService loadData " + params);
    }
}
  • 2.自定义MethodInterceptor
代码语言:javascript
复制
public class RetrofitMethodInterceptor implements MethodInterceptor {

    @Override
    public Object intercept(Object sub, Method arg1, Object[] objects, MethodProxy methodProxy) throws Throwable {
        System.out.println("======插入前置通知======");
        if(arg1.getName().equals("loadData") && objects[0] instanceof String) {
            objects[0] = "aaaaaaaaaaa";
        }
        Object object = methodProxy.invokeSuper(sub, objects);
        System.out.println("======插入后者通知======");
        return object;
    }
}
  • 3.测试代码
代码语言:javascript
复制
public class Main {

    public static void main(String[] args) {
        // 代理类class文件存入本地磁盘方便我们反编译查看源码
        System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "../");
        // 通过CGLIB动态代理获取代理对象的过程
        Enhancer enhancer = new Enhancer();
        // 设置enhancer对象的父类
        enhancer.setSuperclass(RetrofitService.class);
        // 设置enhancer的回调对象
        enhancer.setCallback(new RetrofitMethodInterceptor());
        // 创建代理对象
        RetrofitService proxy = (RetrofitService) enhancer.create();
        // 通过代理对象调用目标方法
        proxy.loadData("lalalalalala");
    }
}
  • 4.查看代理类 加了System.setProperty这句话会在对应的目录下生成对应的包名,里面就会有对应的代理类,里面一共有三个文件,我们暂时只需要这个 RetrofitService$$EnhancerByCGLIB$$158ba096
代码语言:javascript
复制
public final void loadData(final String s) {
        MethodInterceptor cglib$CALLBACK_2;
        MethodInterceptor cglib$CALLBACK_0;
        if ((cglib$CALLBACK_0 = (cglib$CALLBACK_2 = this.CGLIB$CALLBACK_0)) == null) {
            CGLIB$BIND_CALLBACKS(this);
            cglib$CALLBACK_2 = (cglib$CALLBACK_0 = this.CGLIB$CALLBACK_0);
        }
        if (cglib$CALLBACK_0 != null) {
            cglib$CALLBACK_2.intercept((Object)this, RetrofitService$$EnhancerByCGLIB$$158ba096.CGLIB$loadData$0$Method, new Object[] { s }, RetrofitService$$EnhancerByCGLIB$$158ba096.CGLIB$loadData$0$Proxy);
            return;
        }
        super.loadData(s);
    }

可以看到会调用我们自定义的intercept.整个过程其实和jdk动态代理类似

https://blog.csdn.net/yhl_jxy/article/details/80633194

http://ifeve.com/cglib-desc/

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1.cglib介绍
  • 2.简单Demo
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档