Cglib方法实现动态代理
除了使用JDK方式产生动态代理外,Java还给我们提供了另外一种产生动态代理的方法,那就是使用cglib。
cglib是这样实现动态代理的:
· ①.针对类来实现代理
· ②对指定目标类产生一个子类 ,通过方法拦截技术拦截所有父类方法的调用。
·
cglib的实现机制与Java 动态代理不同,它是通过继承实现的 ,它也是动态创建了一个类,但这个类的父类是被代理的类,代理类重写了父类的所有public非final方法,改为调用Callback中的相关方法,在本例中,调用CglibProxy的intercept方法。
具体实现步骤如下:
1.我们先新建一个普通的Java项目,然后,在使用这个方法之前,我们需要给项目导入所需的jar包。
cglib-nodep-2.2.jar
2.建立被代理类
package cglibProxy;
public class Person {
public void work(){
System.out.println(工作中..);
}
}
简单起见,我们这里只给Person类实现一个work()方法,用于模拟业务实现。
3.接下来就是最重要的一点,建立代理类,代理类需要实现以下接口:
interface MethodInterceptor{}
这个接口需要我们导入jar包后才会出现,顾名思义,也就是方法拦截器。
代理类的实现细节如下:
package cglibProxy;
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 CglibProxy implements MethodInterceptor {
private Enhancer enhancer = new Enhancer();
public Object getProxy(Class clazz){
//设置创建子类的类,即指定为哪个类产生代理类
enhancer.setSuperclass(clazz);
/*设置回调函数
* setCallback设置被代理类的public非final方法被调用时的处理类
* 这个例子中我们设置的方法为Person中的work()方法
* 当work()方法被调用时,由该类进行处理
* */
enhancer.setCallback(this);
//创建子类实例
return enhancer.create();
}
/*
* 作用:拦截所有目标类方法的调用
* 参数:
* 1. obj --目标类的实例对象
* 2. method--目标方法的反射对象
* 3. args --方法的参数
* 4. proxy --代理类的实例对象
* */
@Override
public Object intercept(Object obj, Method method, Object[] args,
MethodProxy proxy) throws Throwable {
System.out.println(代理类开始介入..);
//代理类调用父类的方法
proxy.invokeSuper(obj, args);
System.out.println(代理类介入结束);
return null;
}
}
这里出现了一个比较少见的类Enhancer,查阅官方API,有这么一段注解:
/*Generates dynamic subclasses to enable method interception.
This class started as a substitute for the standard Dynamic Proxy
support included with JDK 1.3, but one that allowed the proxies
interfaces. The dynamically generated subclasses override
the non-final methods of the superclass and have hooks which
callback to user-defined interceptor implementations.*/
翻译过来大概意思就是:
/*生成动态子类以启用方法拦截。
这个类开始替代了JDK 1.3中包含的标准动态代理支持,
但是允许代理扩展一个具体的基类,以及实现接口。
动态生成的子类覆盖超类的非最终方法,
并具有回调到用户定义的拦截器实现的钩子。*/
其实Enhancer类是CGLib中的一个字节码增强器,它可以方便的对你想要处理的类进行扩展。
我们通过在代理类中聚合一个Enhancer类的一个实例对象,然后调用Enhancer实例对象的相应方法,对父类的调用方法进行拦截。
代理类返回代理对象由getProxy()方法实现,其中:
enhancer.setSuperclass(clazz);
/*官方API对该类的注解如下:
*Set the class which the generated class will extend.
*翻译:
*设置生成的类将要继承的类
*这样比较难懂,从方法名中我们可以看出,这其实就是设置代理类的父类
*/
与JDK动态代理不同,CglibProxy中没有被代理的对象,它通过MethodProxy类的实例对象proxy的invokeSuper方法调用被代理类的方法:
proxy.invokeSuper(obj, args);
但是,要注意的是,它不能这样调用被代理类的方法:
proxy.invoke(obj, args);
因为proxy是代理对象,调用这个方法还会调用到CglibProxy的intercept方法,造成死循环。
3.最后,我们建立测试类
package cglibProxy;
public class Test {
public static void main(String[] args) {
//在main方法中,没有创建被代理的对象,创建的对象直接就是代理对象。
CglibProxy proxy = new CglibProxy();
//getProxy()方法返回代理方法产生的实例对象
Person person = (Person)proxy.getProxy(Person.class);
//代理对象调用wokr()方法
person.work();
}
}
运行结果:
代理类开始介入..
工作中..
代理类介入结束
动态代理是实现面向切面的编程(AOP – Aspect Oriented Programming)的基础,所以,了解动态代理的实现方法和机制是很有必要的,通过一个简单的实例,可以对动态代理有初步的认识,为以后的深入学习打下基础。
Cglib方法实现动态代理的更多相关文章
- 学习CGLIB与JDK动态代理的区别
动态代理 代理模式是Java中常见的一种模式.代理又分为静态代理和动态代理.静态代理就是显式指定的代理,静态代理的优点是由程序员自行指定代理类并进行编译和运行,缺点是一个代理类只能对一个接口的实现类进 ...
- Cglib 与 JDK动态代理的运行性能比较
都说 Cglib 创建的动态代理的运行性能比 JDK 动态代理能高出大概 10 倍,今日抱着怀疑精神验证了一下,发现情况有所不同,遂贴出实验结果,以供参考和讨论. 代码很简单,首先,定义一个 Test ...
- CGlib和JDK动态代理
一.CGlib动态代理 JDK实现动态代理需要实现类通过接口定义业务方法,对于没有接口的类,如何实现动态代理呢,这就需要CGLib了.CGLib采用了非常底层的1:字节码技术,其原理是通过字节 ...
- Cglib 与 JDK动态代理
作者:xiaolyuh 时间:2019/09/20 09:58 AOP 代理的两种实现: jdk是代理接口,私有方法必然不会存在在接口里,所以就不会被拦截到: cglib是子类,private的方法照 ...
- 性能优于JDK代理,CGLib如何实现动态代理
按照代理的创建时期,代理类可以分为两种. 静态代理:由程序员创建或特定工具自动生成源代码,再对其编译.在程序运行前,代理类的.class文件就已经存在了. 动态代理:在程序运行时,运用反射机制动态创建 ...
- 死磕Spring之AOP篇 - 初识JDK、CGLIB两种动态代理
该系列文章是本人在学习 Spring 的过程中总结下来的,里面涉及到相关源码,可能对读者不太友好,请结合我的源码注释 Spring 源码分析 GitHub 地址 进行阅读. Spring 版本:5.1 ...
- 面试造火箭系列,栽在了cglib和jdk动态代理
"喂,你好,我是XX巴巴公司的技术面试官,请问你是张小帅吗".声音是从电话那头传来的 "是的,你好".小帅暗喜,大厂终于找上我了. "下面我们来进行一 ...
- 基于 CGLIB 库的动态代理机制
之前的文章我们详细的介绍了 JDK 自身的 API 所提供的一种动态代理的实现,它的实现相对而言是简单的,但是却有一个非常致命性的缺陷,就是只能为接口中的方法完成代理,而委托类自己的方法或者父类中的方 ...
- java提供类与cglib包实现动态代理
终于有点空余时间,决定把之前学习的知识点整理一下,备以后复习. 动态代理有三角色:抽象角色,代理角色,真是角色. 第一个记录下java提供的动态代理.即使用Proxy类和InvocationHande ...
随机推荐
- JAVA 实现XML与JSON 相互转换
原文地址https://blog.csdn.net/congcong68/article/details/39029907 在工作中,经常碰到XML转为JSON或者JSON转为XML,在这过程中有时嵌 ...
- 百度知道里关于C++的讨论
1.把C++当成一门新的语言学习(和C没啥关系!真的.): 2.看<Thinking In C++>,不要看<C++变成死相>: 3.看<The C++ Programm ...
- 021-centos6.5上二进制安装mysql5.7.22
思路: 下载上传mysql的二进制安装包. 准备好mysql的用户.安装目录basedir.数据目录datadir.配置文件/etc/my.cnf. 初始化出数据库. 配置启动服务. 开机启动. 配置 ...
- BufferedImage操作图片笔记(转)
BufferedImage是Image的一个子类,BufferedImage生成的图片在内存里有一个图像缓冲区,利用这个缓冲区我们可以很方便的操作这个图片,通常用来做图片修改操作如大小变换.图片变灰. ...
- uva12083 二分图 求最大独立集 转化为求最大匹配 由题意推出二分图
这题大白书例题 : Frank 是一个思想有些保守的高中老师,有一次,他需要带一些学生出去旅行,但又怕其中一些学生在旅途中萌生爱意.为了降低这种事情的发生概率,他决定确保带出去的任意两个学生至少要满足 ...
- Js基础知识3-字符串、正则表达式全解
字符串的生成转换 你可以将任何类型的数据都转换为字符串,你可以用下面三种方法的任何一种: var myStr = num.toString(); // "19" var myStr ...
- 关于RSU和股票期权(Stock Option)
最近,和有些猎头沟通时,他们提到RSU的概念,特地搜了下,其和股票期权(Stock Option)差别如下: RSU 和Option 一般都是逐年实现的,比如Offer Letter签三年,上写的给你 ...
- 基于Swoole和Redis实现的并发队列处理系统
背景 由于PHP不支持多线程,但是作为一个完善的系统,有很多操作都是需要异步完成的.为了完成这些异步操作,我们做了一个基于Redis队列任务系统. 大家知道,一个消息队列处理系统主要分为两大部分:消费 ...
- linux内核分析 第7章读书笔记——《深入理解计算机系统》
第七章 链接 --<深入理解计算机系统> 链接是将各种代码和数据部分收集起来并组合成为一个单一文件的过程,这个文件可被加载(或拷贝)到存储器并执行. 一.编译器 大多数编译系统提供编译驱动 ...
- 认识epoll
linux下的epoll(7)函数,其有着良好的就绪事件通知机制.Epoll 是被linux2.6开始引进的,但是不被其他的类UNIX系统支持,它提供了一种类似select或poll函数的机制:a. ...