Java JDK与cglib * 有什么区别
作者:王佑辉 发布时间:2023-07-23 08:10:15
标签:Java,JDK,cglib, ,
一、说明
1.spring aop中的 * 主要有两种方式,jdk * 和cglib *
2.从实现接口、继承父类的角度讨论区别
3.从限制角度讨论区别
4.从性能上讨论区别
二、区别
1.jdk * 只提供实现接口的目标类代理,不支持没有实现接口的目标类的代理。如果目标类没有实现接口,只能用cglib代理
2.jdk * 会在运行时为目标类生成一个 * 类$proxy*.class。cglib的底层是通过ASM在运行时动态生成目标类的子类,还会有其它类
3. jdk * 的代理类实现了目标类实现的接口,并且会实现接口所有方法来代码增强。cglib * 会重写父类所有的方法来代码增强
4.jdk * 调用时先去调用处理类进行增强,再通过反射的方式调用目标类的方法。cglib * 调用时先通过代理类进行增强,再直接调用父类对应的方法进行调用目标方法
5.jdk * 如果目标类未实现接口则无法代理,cglib是通过继承的方式来 * ,若目标类被final关键字修饰,则无法使用cglib做 *
6.性能上:在老版的jdk,jdk代理生成的类速度快,通过反射调用慢,cglib是jdk代理速度的10倍左右,jdk在版本每次升级都会有很大的性能提升,cglib停滞不前,jdk7 8的 * 性能在1万次实验中比cglib要快20%左右
三、代码示例
3.1 静态代理
package com.proxy.staticproxy;
public interface SellTicket {
void sell();
}
package com.proxy.staticproxy;
public class TrainStation implements SellTicket{
@Override
public void sell() {
System.out.println("火车站售票");
}
}
package com.proxy.staticproxy;
public class ProxyPoint implements SellTicket{
//声明火车类对象
private TrainStation trainStation = new TrainStation();
@Override
public void sell() {
System.out.println("代售点收取服务费");
trainStation.sell();
}
public static void main(String[] args) {
ProxyPoint proxyPoint = new ProxyPoint();
proxyPoint.sell();
}
}
3.2 jdk *
package com.proxy.jdkproxy;
import com.proxy.staticproxy.SellTicket;
import com.proxy.staticproxy.TrainStation;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class ProxyFactory {
private TrainStation trainStation = new TrainStation();
public SellTicket getProxyPoint() {
/**
* ClassLoader loader: 类加载器,用于加载代理类。可以通过目标对象获取类加载器
* Class<?>[] interfaces: 代理类实现的接口的字节码对象
* InvocationHandler h: 代理对象的调用处理程序
*/
SellTicket sellTicket = (SellTicket)Proxy.newProxyInstance(trainStation.getClass().getClassLoader(), trainStation.getClass().getInterfaces(),
new InvocationHandler() {
/**
* @param proxy 代理对象 proxyObject是同一个对象,在invoke方法中基本不用
* @param method 对接口中的方法进行封装的method对象
* @param args 调用方法的实际参数
* @return 方法返回值
* @throws Throwable
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 代码增强
System.out.println("代理点收取服务费");
Object object = method.invoke(trainStation, args);
return object;
}
});
return sellTicket;
}
public static void main(String[] args) {
ProxyFactory proxyPoint = new ProxyFactory();
SellTicket sellTicket = proxyPoint.getProxyPoint();
sellTicket.sell();
}
}
3.3 cglib *
<!-- 引入cglib依赖包-->
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>2.2.2</version>
</dependency>
package com.cglib;
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 ProxyFactory implements MethodInterceptor {
private TrainStation trainStation = new TrainStation();
public TrainStation getTrainStation(){
//创建Enhancer对象,类似于JDK代理中的Proxy类
Enhancer enhancer = new Enhancer();
//设置父类的字节码对象
enhancer.setSuperclass(TrainStation.class);
//设置回调函数
enhancer.setCallback(this);
//创建代理对象
TrainStation trainStation = (TrainStation)enhancer.create();
return trainStation;
}
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
// 代码增强
System.out.println("代售点收取服务费用");
Object obj = method.invoke(trainStation, objects);
return obj;
}
public static void main(String[] args) throws Exception {
ProxyFactory proxyFactory = new ProxyFactory();
TrainStation trainStation = proxyFactory.getTrainStation();
trainStation.sell();
}
}
来源:https://blog.csdn.net/qq_32088869/article/details/129655075


猜你喜欢
- 前文传送门:Netty分布式Future与Promise执行回调相关逻辑剖析概述FastThreadLocal我们在剖析堆外内存分配的时候简
- ListView是android中最常用的控件之一。 在实际运用中往往会遇到一次性加载全部数据过多,需要分页加载增加程序运行效率! 本dem
- 1.前言NameServer主要作用是为消息消费者和消息生产者提供关于主题Topic的路由信息,那么NameServer需要存储路由的基本信
- C#接口的学习,在编程中,我们经常会用到接口,那什么是接口呢?接口描述的是可属于任何类或结构的一组相关功能,所以实现接口的类或结构必须实现接
- 前言本文主要给大家介绍了关于Java中Arraylist动态扩容的相关内容,分享出来供大家参考学习,下面话不多说了,来一起看看详细的介绍吧。
- 本文实例为大家分享了C#实现扫雷游戏的具体代码,供大家参考,具体内容如下一、实验目的:1、掌握c#窗体和控件的常用属性和功能2、完成扫雷游戏
- 一、题目描述题目实现:网络通信,实现信息的发送和接收。二、解题思路创建一个服务器类:ServerSocketFrame,继承JFrame类写
- 题目:企业发放的奖金根据利润提成。利润(I)低于或等于10万元时,奖金可提10%;利润高于10万元,低于20万元时,低于10万元的部分按10
- 有时候,我们在同一个activity里面有很多fragment,在横竖屏的时候,有些fragment要求重新加载数据,有些不需要,如何简单控
- 前言众所周知Spring Boot是非常高效的开发框架,lombok是一套代码模板解决方案,将极大提升开发的效率,这里介绍给大家使用。文中详
- springboot整合vue实现上传下载文件,供大家参考,具体内容如下环境springboot 1.5.x完整代码下载:springboo
- 前言本文是我之前写的这篇文章《Android图文混排-实现EditText图文混合插入上传》的升级版,除了在EditText实现了图片上传之
- 一、LinkedHashMap的类继承关系二、源码分析1.自己对LinkedHashMap的理解从继承关系上,我们看到LinkedHashM
- 一:Android 中Home键监听和Back键监听的区别:(1).在Android中,当按下Home键的时候,默认情况下Stop前台的Ac
- 我们今天来聊下如何做实时通讯(先给知识点,实现原理,最后给出实现实时通信的具体代码--使用工具 android studio)现在先说下用到
- 一、简介使用了static 修饰符的方法为静态方法,反之则是非静态方法。 静态方法是一种特殊的成员方法,它不属于类的某一个具体的实
- 为什么会有常量池的概念?不知道小伙伴们是否有思考过这个问题? 没有思考也无所谓,小编在这里类比一下,大家就会清晰了。什么是池? 我们听的最多
- Service是什么 Service是一个android 系统中的应用程序组件,它跟Activity的级别差不多,但是他没有图形化界面,不能
- spring mvc中的@PathVariable是用来获得请求url中的动态参数的,十分方便,复习下: @Controller publ
- 前言现在很多应用都会用到地图,但是我们肯定不想自己的app中还要弄个导航神马的,所以第三方的地图也为我们开辟了一条捷径,直接将数据传输到地图