学习CGLIB与JDK动态代理的区别
动态代理
- 代理模式是Java中常见的一种模式。代理又分为静态代理和动态代理。静态代理就是显式指定的代理,静态代理的优点是由程序员自行指定代理类并进行编译和运行,缺点是一个代理类只能对一个接口的实现类进行包装,多个代理类存在重复代码,因此可以定义这样一个代理类,它能代理所有实现类的方法调用:根据传进来的实现类和方法名进行具体调用。——这就是动态代理。
JDK动态代理
- 先上代码,一个接口类
package com.example.demo; public interface IWrite {
//写
void write();
}IWrite
- 一个实现类
package com.example.demo; public class Author implements IWrite {
@Override
public void write() {
System.out.println("writing");
}
} - 最后是代理类
package com.example.demo; import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy; public class AuthorProxy implements InvocationHandler { private Object target; public Object bind(Object target) {
this.target = target; //接收业务实现类对象参数 //通过反射机制,创建一个代理类对象实例并返回。用户进行方法调用时使用
//创建代理对象时,需要传递该业务类的类加载器(用来获取业务实现类的元数据,在包装方法是调用真正的业务方法)、接口、handler实现类
return Proxy.newProxyInstance(this.target.getClass().getClassLoader(),
this.target.getClass().getInterfaces(),this); } @Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("before");
method.invoke(target,args);
System.out.println("after");
return null;
} public static void main(String args[]) {
Author write = new Author();
AuthorProxy authorProxy = new AuthorProxy();
IWrite author = (IWrite) authorProxy.bind(write); author.write(); }
} - jdk动态代理:代理所有“实现的有接口”的目标类。使用内置的Proxy实现动态代理有一个问题:被代理的类必须实现接口,未实现接口则没办法完成动态代理。
CGLib动态代理
- 还是先上代码,一个不继承接口的业务类
package com.example.demo; public class AuthorNoImplements {
public void write() {
System.out.println("writing...");
}
} - 最后是代理实现与测试
package com.example.demo; import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy; import java.lang.reflect.Method; public class CglibProxy implements MethodInterceptor { private Object target; // 这里的目标类型为Object,则可以接受任意一种参数作为被代理类,实现了动态代理
public Object bind(Object target) {
this.target = target;
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(this.target.getClass());
enhancer.setCallback(this);
return enhancer.create();
}
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("before");
Object obj = method.invoke(target, objects);
System.out.println("after");
return obj;
} public static void main(String args[]) {
CglibProxy cglibProxy = new CglibProxy();
AuthorNoImplements authorNoImplements = (AuthorNoImplements) cglibProxy.bind(new AuthorNoImplements());
authorNoImplements.write();
}
} CGlib动态代理是通过继承业务类,生成的动态代理类是业务类的子类,通过重写业务方法进行代理;
CGLib 与JDK动态代理的区别
- 最后说一下二者的区别:
- JDK代理是不需要以来第三方的库,只要要JDK环境就可以进行代理,它有几个要求
* 实现InvocationHandler
* 使用Proxy.newProxyInstance产生代理对象
* 被代理的对象必须要实现接口 - CGLib 必须依赖于CGLib的类库,但是它需要类来实现任何接口代理的是指定的类生成一个子类,覆盖其中的方法,是一种继承但是针对接口编程的环境下推荐使用JDK的代理。
学习CGLIB与JDK动态代理的区别的更多相关文章
- Cglib 与 JDK动态代理
作者:xiaolyuh 时间:2019/09/20 09:58 AOP 代理的两种实现: jdk是代理接口,私有方法必然不会存在在接口里,所以就不会被拦截到: cglib是子类,private的方法照 ...
- Cglib 与 JDK动态代理的运行性能比较
都说 Cglib 创建的动态代理的运行性能比 JDK 动态代理能高出大概 10 倍,今日抱着怀疑精神验证了一下,发现情况有所不同,遂贴出实验结果,以供参考和讨论. 代码很简单,首先,定义一个 Test ...
- 面试造火箭系列,栽在了cglib和jdk动态代理
"喂,你好,我是XX巴巴公司的技术面试官,请问你是张小帅吗".声音是从电话那头传来的 "是的,你好".小帅暗喜,大厂终于找上我了. "下面我们来进行一 ...
- 输出cglib以及jdk动态代理产生的class文件
--该设置用于输出jdk动态代理产生的类 System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles&q ...
- CGlib和JDK动态代理
一.CGlib动态代理 JDK实现动态代理需要实现类通过接口定义业务方法,对于没有接口的类,如何实现动态代理呢,这就需要CGLib了.CGLib采用了非常底层的1:字节码技术,其原理是通过字节 ...
- spring cglib 与 jdk 动态代理
1. 概述 JDK动态代理是利用java反射机制 生成一个实现接口的匿名类, 在调用具体方法前调用InvocationHandler来处理 Cglib动态代理是 利用asm开源包 把被代理类的clas ...
- CGLIB和Java动态代理的区别(笔记)
java常用知识点: 1.Java动态代理只能够对接口进行代理,不能对普通的类进行代理(因为所有生成的代理类的父类为Proxy,Java类继承机制不允许多重继承):CGLIB能够代理普通类:2.Jav ...
- 有点深度的聊聊JDK动态代理
在接触SpringAOP的时候,大家一定会被这神奇的功能所折服,想知道其中的奥秘,底层到底是如何实现的.于是,大家会通过搜索引擎,知道了一个陌生的名词:动态代理,慢慢的又知道了动态代理有多种实现方式, ...
- spring源码学习【准备】之jdk动态代理和cglib动态代理的区别和性能
一:区别:---->JDK的动态代理依靠接口实现,如果有些类并没有实现接口,则不能使用JDK代理,这就要使用cglib动态代理了.--->JDK的动态代理机制只能代理实现了接口的类,而不能 ...
随机推荐
- linux arm 交叉编译ACE(ubuntu16.04)
解压ace包 tar zxvf ACE_6.1.0.tar.gz 在终端设置环境变量 sudo gedit /etc/profile 在打开的内容添加 export ACE_ROOT=/home/xx ...
- 全网最详细的IDEA、Eclipse和MyEclipse之间于Java web项目发布到Tomcat上运行成功的对比事宜【博主强烈推荐】【适合普通的还是Maven方式创建的】(图文详解)
不多说,直接上干货! IDEA [适合公司业务]全网最详细的IDEA里如何正确新建[普通或者Maven]的Java web项目并发布到Tomcat上运行成功[博主强烈推荐](类似eclipse里同一个 ...
- 从零开始学 Web 之 JS 高级(三)apply与call,bind,闭包和沙箱
大家好,这里是「 从零开始学 Web 系列教程 」,并在下列地址同步更新...... github:https://github.com/Daotin/Web 微信公众号:Web前端之巅 博客园:ht ...
- Go HTTP服务器
HTTP HandleFunc的简单使用 package main import ( "log" "net/http" ) func main() { //注册 ...
- mybatis教程3(映射文件)
MyBatis 的真正强大在于它的映射语句,也是它的魔力所在.由于它的异常强大,映射器的 XML 文件就显得相对简单.如果拿它跟具有相同功能的 JDBC 代码进行对比,你会立即发现省掉了将近 95% ...
- IdentityServer4 中文文档 -10- (快速入门)使用密码保护API
IdentityServer4 中文文档 -10- (快速入门)使用密码保护API 原文:http://docs.identityserver.io/en/release/quickstarts/2_ ...
- 解决System.Data.SqlClient.SqlException (0x80131904): Timeout 时间已到的问题
这段时间写Android和IOS服务时 sql数据库查询有数据正常,没数据总是报异常:System.Data.SqlClient.SqlException (0x80131904): Timeout ...
- Abp中自定义Exception的HttpStatusCode
Abp中在新版本中,抛出的异常(比如:UserFriendlyException)通过AjaxResponse封装后返回的时候,HttpStatusCode默认指定成了500. 对于一些默认封装好的处 ...
- Flume参数小结
名词解释: 1.netcat:通过网络端口获取数据,source的实现类 2.logger:将数据显示到控制台,sink的实现类 3.memory: ,channel的实现类 4.capacity:是 ...
- Ubuntu下JDK1.8安装后配置环境变量
export JAVA_HOME=/dengyang/jdk1.8.0_56export JRE_HOME=$JAVA_HOME/jreexport CLASSPATH=.:$JAVA_HOME/li ...