cglib动态代理和retrofit

2019-09-28  本文已影响0人  勇敢地追

1.cglib介绍

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

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地址有)

public class RetrofitService {
    public void loadData(String params) {
        System.out.println("RetrofitService loadData " + params);
    }
}
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;
    }
}
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");
    }
}
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/

上一篇 下一篇

猜你喜欢

热点阅读