Java 代理学习笔记 —— 浅析Cglib动态代理实现

本文详细介绍了Cglib动态代理的实现机制,包括如何通过继承委托类生成代理类,Cglib的FastClass在减少反射调用时间中的作用,以及Cglib代理与Java原生代理的差异。通过示例代码展示了Cglib代理的创建和工作原理,揭示了Cglib在生成代理对象和方法调用时的文件生成过程。
摘要由CSDN通过智能技术生成

简述

上一篇博客中,我们仔细地分析了Java原生代理的实现机制,得出了如下结论
- 代理的类动态生成的。也就是说,在程序运行时创建类的字节码,并且动态加载到JVM中
- Java原生代理实际上是创造了一个实现了所有给定接口的类,并在调用接口的方法的时候使用反射达到代理效果
基于以上两点,我们能得出结论,如果要使用Java原生代理的话,就必须将类的每一个方法都写在接口里面再进行实现。而Cglib的出现,就解决了这个问题。在Cglib Github主页上我们能看到如此描述

Cglib(Code Generation Library) 能够提供生成和转换Java字节码的API,它被广泛运用在AOP,测试,数据处理以及生成动态代理和方法拦截的框架中。

接下来,我们看一下Cglib是如何工作的。

Cglib Proxy 示例

对于Cglib的代理对象,与Java原生代理对象相同,它们都需要生成一个代理类对代理对象进行持有,同时必须在生成这个代理类的时候,将一个回调方法处理类作为参数传入构造函数中。这样,当代理类的任意方法被调用的时候,Java原生代理会调用InvocationHandler中的invoke方法,而Cglib代理则会调用MethodInterceptor中的intercept方法。
仍然以前面博客中的UserDao以及UserDaoImpl为例进行代码示例。
SimpleMethodInterceptor.java

package com.study.cglib.learning;

import java.lang.reflect.Method;

import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

public class SimpleMethodInterceptor implements MethodInterceptor{
   

    public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
        System.out.println("proxy control!");
        //注意,如果使用invoke方法,并且参数也为代理类,则会循环进入此拦截方法从而导致爆栈
        //invokeSuper即为调用原生的方法
        return proxy.invokeSuper(obj, args);
    }

    public Object createProxy(Class<?> clazz, Class<?>[] interfaces) {
        Enhancer enhancer = new Enhancer();
        //设置需要代理的类
        enhancer.setSuperclass(clazz);
        //设置需要代理的接口
        enhancer.setInterfaces(interfaces);
        //设置处理方法的回调函数
        enhancer.setCallback(this);
        //设置回掉函数的过滤方法
        enhancer.setCallbackFilter(new SimpleCallBackfilter());
        return enhancer.create();
    }
}

SimpleCallBackfilter.java

public class SimpleCallBackfilter implements CallbackFilter{
   

    @Override
    public int accept(Method method) {
        System.out.println("filtering!");
        return 0;
    }

}

我们可以为代理类设置多个回调方法(将回调类以数组形式传入setCallBacks方法中),然后再设置callBackFilter,callBackFilter返回的整型代表着第几个回调类的拦截方法将会被调用。

App.java

package com.study.cglib.learning;

public class App 
{
   
    public static void main( String[] args )
    {
        SimpleMethodInterceptor cgProxy = new SimpleMethodInterceptor();

        UserDao userDao = (UserDao) cgProxy.createProxy(UserDaoImpl.class, null);

        userDao.queryName();
        //输出 : filtering!
        //      filtering!
        //      filtering!
        //      filtering!
        //      filtering!
        //      filtering!
        //      proxy control!
        //      getUserName
    }
}

浅析Cglib生成代理类的方式

Enhancer.class通过继承AbstractClassGenerator,并且实现了generateClass来进行代理类的字节码动态生成,其方式和过程与Java原生代理类似,找到所有声明的方法,构建构造函数,构建代理函数,最后根据内存中生成的所有函数,拼凑成字节码。唯一不同的是,Cglib**直接继承**委托类。而CallBackFilter实际上也是在生成函数的时候生效的,如下所示。
Enhancer.emitMethods


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值