cglib代理的使用
一、什么是CGLIB?
总的来说,无论是cglib、jdk动态代理又或者是aop面向切面编程,都运用到了一个最重要的设计模式--代理模式!万变不离其终,学好代理模式,打遍天下无敌手!
cglib就是一个字节码生成
和转换
的库嘛!这倒是不难理解,它主要被AOP,测试,数据访问框架用来生成动态代理对象
和拦截字段访问
。
今天我们就来说说cglib在代理方面的应用!
二、CGLIB源码粗略解读!
首先我们来看看cglib源码的包结构:
从cglib核心包中可以看到有个proxy
的包,我们一起去探个究竟!展开proxy
可以发现:
在该包中的Enhancer
类和MethodInterceptor
接口是整个包的核心所在!Enhancer
就是“增强”的意思嘛!主要用于生成动态子类
以启用方法拦截,什么意思?这样子讲!cglib类代理的基本思想就是对被代理类生成一个新的类(proxy
),该类是继承自被代理类的,并对被代理类方法执行前后执行一些操作,这些操作的通常就是一些回调操作,可以是MethodInterceptor
,LazyLoader
,CallbackFilter
,其中MethodInterceptor
是最常用的。
所有被Enhancer
关联的对象默认都是实现Factory
接口的,该接口提供了一组可以设置对象回调类型的方法,你可以通过调用setUseFactory(false)
取消此特性!
需要注意的是,cglib是无法代理final
修饰的方法的,因为这是java语言规范决定的!
MethodInterceptor
是一个提供环绕通知
的通用回调接口!Aop中有这样的术语,那就是前置通知
,后置通知
,环绕通知
,非常好理解,就是一个在方法执行前的通知,一个方法执行后的通知,另外一个就是方法执行前后都通知。
该接口只有一个intercept()
方法:
public Object intercept(Object obj, java.lang.reflect.Method method, Object[] args,MethodProxy proxy) throws Throwable;
复制代码
所有对被代理类方法的执行都会跳转到这个方法上面来,而原来的方法则通过反射得到的Method
对象或者MethodProxy
对象进行调用。
三、老规矩,来个栗子一起团圆!
import java.lang.reflect.Method;import net.sf.cglib.proxy.Callback;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;class Student {private String name = "zhangsan";public String getStuName() {return name;}}public class CglibMethodInterceptTest {public static void main(String[] args) {//创建一个Enhancer对象Enhancer enchaner = new Enhancer();//设置被代理的类enchaner.setSuperclass(Student.class);//创建一个回调接口Callback interceptor = new MethodInterceptor() {@Overridepublic Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy)throws Throwable {System.err.println("原方法名是 : " + method.getName());System.err.println("原方法声明的类为 " + method.getDeclaringClass());System.err.println("我是 " + (String) proxy.invokeSuper(obj, args));System.err.println("我调用结束了");return null;}};enchaner.setCallback(interceptor);Student student = (Student) enchaner.create();student.getStuName();}
}
复制代码
输出的结果为:
原方法名是 : getStuName
原方法声明的类为 class wokao666.test.Student
我是 zhangsan
我调用结束了
复制代码
过滤器的使用
package wokao666.test;import java.lang.reflect.Method;import net.sf.cglib.proxy.Callback;
import net.sf.cglib.proxy.CallbackFilter;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import net.sf.cglib.proxy.NoOp;class Student {private String name = "zhangsan";private String rename = "rename";public String getStuName() {return name;}public String getRename() {return rename;}}public class CglibMethodInterceptTest {public static void main(String[] args) {//创建一个Enhancer对象Enhancer enchaner = new Enhancer();//设置被代理的类enchaner.setSuperclass(Student.class);//创建一个回调接口Callback interceptor = new MethodInterceptor() {@Overridepublic Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy)throws Throwable {System.err.println("原方法名是 : " + method.getName());System.err.println("原方法声明的类为 " + method.getDeclaringClass());System.err.println("我是 " + (String) proxy.invokeSuper(obj, args));System.err.println("我调用结束了");return proxy.invokeSuper(obj, args);}};CallbackFilter callbackFilter = new CallbackFilter() {@Overridepublic int accept(Method method) {int flag = 0;if ("getStuName".equals(method.getName())) {System.err.println("我将此方法过滤掉了,不对该方法进行拦截");return 1;}return 0;}};Callback[] callbacks = new Callback[] { interceptor, NoOp.INSTANCE };enchaner.setCallbackFilter(callbackFilter);enchaner.setCallbacks(callbacks);Student student = (Student) enchaner.create();System.err.println(student.getStuName());System.err.println(student.getRename());}
}
复制代码
我将此方法过滤掉了,不对该方法进行拦截
zhangsan
原方法名是 : getRename
原方法声明的类为 class wokao666.test.Student
我是 rename
我调用结束了
rename
复制代码
NoOp.INSTANCE
:这个NoOp
表示no operator
,即什么操作也不做,代理类直接调用被代理的方法不进行拦截。
getStuName
对应的CallbackFilter中定义的索引1,在Callback[]
数组中使用的过滤为NoOp
,因此直接执行了被代理方法。
getRename
对应CallbackFilter中定义的索引0,在Callback[]
数组中使用的过滤为interceptor
,因此执行了方法拦截器进行拦截。
我写的只是一点皮毛,建议大家在此基础上多动手,结合源代码多写写一些例子,写多了,懂得就多了!
cglib代理的使用相关推荐
- Java动态代理与Cglib代理
为什么80%的码农都做不了架构师?>>> 最近又继续回来死磕Spring源码,以前看的也忘得差不多了,这次先把Spring使用的动态代理cglib看了一下,打好基础知识. cg ...
- 基于Spring AOP的JDK动态代理和CGLIB代理
一.AOP的概念 在软件业,AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术.AOP是OOP的 ...
- Spring中AOP的两种代理方式(Java动态代理和CGLIB代理)
第一种代理即Java的动态代理方式上一篇已经分析,在这里不再介绍,现在我们先来了解下GCLIB代理是什么?它又是怎样实现的?和Java动态代理有什么区别? cglib(Code Generation ...
- 代理模式——静态代理,动态代理(JDK代理和CGLib代理)
概述 由于某些原因需要给某对象提供一个代理以控制对该对象的访问. 这时,访问对象不适合或者不能直接引用目标对象,代理对象作为访问对象和目标对象之间的中介. Java中的代理按照代理类生成时机不同又分为 ...
- CGLIB代理到底是个什么东西?这是一篇最全的CGLIB大全
目录 0 概述 0.1 CGLIB包结构 1 使用CGLIB实现动态代理 1.1 CGLIB代理相关的类 1.2 CGLIB动态代理的基本原理 1.3 使用MethodInterceptor接口实现方 ...
- Java静态代理、动态代理与CGLib代理
java的动态代理举足轻重,它同反射原理一直是许多框架的底层实现.今天唠一下. 一.代理模式 代理模式是一种设计模式,提供了对目标对象额外的访问方式,即通过代理对象访问目标对象,这样可以在不修改原目标 ...
- 手动使用cglib代理(了解)
这个你学会了将来也没啥机会用,将来你要玩AOP,学会了也只是得瑟一下说来手写一个AOP,你看看我是否厉害,你不明白太阳是7个颜色构成的,也不影响你晒太阳,然后呢,AOP这个代码呢,咱们再来一个User ...
- aop实现原理-动态代理CGLib代理
那接下来的话,那咱们Spring当中,这个AOP,咱们先说概念,咱们先不写具体代码,咱们就是聊,聊Spring的AOP,Spring能帮我们干啥呢,我告诉你,Spring他作为对象的容器,Spring ...
- Spring的@Configuration使用cglib代理的效果和我自己写的简单实现
下面的代码,照着复制就能跑起来 今天看了下Spring的@Configuration,即java类配置bean,(这个spring3的新功能,虽然现在已经spring5了,但是这种配置bean的方式也 ...
- Spring强制使用CGLIB代理事务
Spring强制使用CGLIB代理事务 springaopjdkreferenceclasspath Spring1.2: 将事务代理工厂[TransactionProxyFactoryBean] 或 ...
最新文章
- 动态内存检测工具Valgrind
- 使用Genymotion调试出现错误INSTALL_FAILED_CPU_ABI_INCOMPATI
- 数据科学家最需要什么技能?
- php怎么定义索引,PHP未定义的索引/变量
- 模拟耗时操作_在集成测试中模拟耗时的动作
- min-width:100%和max-width:100%的区别
- Dell Kace K1000测试报告
- linux php连接mysql权限不够_PHP LINUX APACHE MYSQL权限挣扎
- 如何在oracle官网下载jdk11,在linux上使用wget从oracle官网下载jdk11
- linux codeblocks汉化
- 惠普重新定义IT基础设施
- 华为 Mate 40 系⁠列详细参数对比,Mate 40\40Pro\40Pro+\40RS
- DFS 003:棋盘问题
- IDEA里面的各种小图标
- smtplib 改为通过SSL 465 发送邮件
- rabbitmq的安装和配置
- 5.PCIe协议分析3-PCIe TLP包详解1
- 福利来了!教你们怎么把整个网站的漂亮小姐姐视频都给爬下来!
- 如何在CentOS上安装和使用Wine
- 5个品牌案例,6张优质模板,帮你快速搞懂「商业模式画布」!
热门文章
- 手把手 | 教你爬下100部电影数据:R语言网页爬取入门指南
- C++标准库中各种排序归纳
- nginx或httpd实现负载均衡tomcat(三)
- QT 5.4.1 for Android Ubuntu QtWebView Demo
- linux 内核参数调整说明
- python中的文档字符串(docString)
- 【引用】在Eclipse中将java Project转换成Dynamic Web Project
- JQuery制作的toolTip,针对图片预览效果
- JAVASCRIPT函数式编程
- Oracle VM VirtualBox安裝Windows 2000失败