Spring CGLlB动态代理实现过程解析
JDK动态代理使用起来非常简单,但是它也有一定的局限性,这是因为JDK动态代理必须要实现一个或多个接口,如果不希望实现接口,则可以使用CGLIB代理。
CGLIB(CodeGenerationLibrary)是一个高性能开源的代码生成包,它被许多AOP框架所使用,其底层是通过使用一个小而快的字节码处理框架ASM(Java字节码操控框架)转换字节码并生成新的类。因此CGLIB要依赖于ASM的包,解压Spring的核心包spring-core-3.2.2.RELEASE.jar,文件目录如图1所示。
在图1中可以看出,解压的核心包中包含cglib和asm,也就是说Spring3.2.13版本的核心包已经集成了CGLIB所需要的包,所以在开发中不需要另外导入ASM的JAR包了。下面通过案例演示实现CGLIB的代理过程。
1.创建目标类GoodsDao
在com.mengma.dao包下创建目标类GoodsDao,在类中定义增、删、改、查方法,并在每个方法编写输出语句,如下所示。
packagecom.mengma.dao; publicclassGoodsDao{ publicvoidadd(){ System.out.println("添加商品..."); } publicvoidupdate(){ System.out.println("修改商品..."); } publicvoiddelete(){ System.out.println("删除商品..."); } publicvoidfind(){ System.out.println("修改商品..."); } }
2.创建代理类MyBeanFactory
在src目录下创建一个名为com.mengma.cglib的包,该包下创建类MyBeanFactory,如下所示。
packagecom.mengma.cglib; importjava.lang.reflect.Method; importorg.springframework.cglib.proxy.Enhancer; importorg.springframework.cglib.proxy.MethodInterceptor; importorg.springframework.cglib.proxy.MethodProxy; importcom.mengma.dao.GoodsDao; importcom.mengma.jdk.MyAspect; publicclassMyBeanFactory{ publicstaticGoodsDaogetBean(){ //准备目标类 finalGoodsDaogoodsDao=newGoodsDao(); //创建切面类实例 finalMyAspectmyAspect=newMyAspect(); //生成代理类,CGLIB在运行时,生成指定对象的子类,增强 Enhancerenhancer=newEnhancer(); //确定需要增强的类 enhancer.setSuperclass(goodsDao.getClass()); //添加回调函数 enhancer.setCallback(newMethodInterceptor(){ //intercept相当于jdkinvoke,前三个参数与jdkinvoke—致 @Override publicObjectintercept(Objectproxy,Methodmethod,Object[]args, MethodProxymethodProxy)throwsThrowable{ myAspect.myBefore();//前增强 Objectobj=method.invoke(goodsDao,args);//目标方法执行 myAspect.myAfter();//后增强 returnobj; } }); //创建代理类 GoodsDaogoodsDaoProxy=(GoodsDao)enhancer.create(); returngoodsDaoProxy; } }
上述代码中,应用了CGLIB的核心类Enhancer。在第19行代码调用了Enhancer类的setSuperclass()方法,确定目标对象。
第21行代码调用setCallback()方法添加回调函数;第24行代码的intercept()方法相当于JDK动态代理方式中的invoke()方法,该方法会在目标方法执行的前后,对切面类中的方法进行增强;第33~34行代码调用Enhancer类的create()方法创建代理类,最后将代理类返回。
3.创建测试类
在com.mengma.cglib包下创建测试类CGLIBProxyTest,编辑后如下所示。
packagecom.mengma.cglib; importorg.junit.Test; importcom.mengma.dao.GoodsDao; publicclassCGLIBProxyTest{ @Test publicvoidtest(){ //从工厂获得指定的内容(相当于spring获得,但此内容时代理对象) GoodsDaogoodsDao=MyBeanFactory.getBean(); //执行方法 goodsDao.add(); goodsDao.update(); goodsDao.delete(); goodsDao.find(); } }
上述代码中,调用getBean()方法时,依然获取的是goodsDao的代理对象,然后调用该对象的方法。使用JUnit测试运行test()方法,运行成功后,控制台的输出结果如图2所示。
从图2的输出结果中可以看出,在调用目标类的方法前后,也成功调用了增强的代码,由此说明,使用CGLIB代理的方式同样实现了手动代理。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。
声明:本文内容来源于网络,版权归原作者所有,内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:czq8825#qq.com(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。