当前位置: 首页 > news >正文

java中的动态代理

JDK动态代理

在这里插入图片描述

  • 知识点

    • JDK动态代理是基于接口的代理,通过反射机制动态生成代理类。
    • 代理类实现了被代理接口,并在代理类中调用InvocationHandler接口的invoke方法来实现对被代理方法的增强。
  • 注意点

    • 被代理类必须实现接口,否则无法使用JDK动态代理。
    • JDK动态代理只能代理实现了接口的类,无法代理没有实现接口的类。
  • 常见场景

    • AOP(面向切面编程):在方法执行前后进行一些额外操作,比如日志记录、性能监控等。
    • 事务管理:在方法执行前后开启、提交或回滚事务。

CGLIB代理

  • 知识点

    • CGLIB代理是基于继承的代理,通过继承被代理类来实现代理。
    • CGLIB代理不要求被代理类实现接口,可以代理没有实现接口的类。
  • 注意点

    • CGLIB代理生成的代理类是被代理类的子类。
    • 由于CGLIB代理是基于继承的,因此无法代理final类和final方法。
  • 常见场景

    • 对没有实现接口的类进行代理。
    • 对类的方法进行增强,而不需要修改原始类的代码。也可以做AOP
  • 问题

  • 请解释JDK动态代理的原理。

  • JDK动态代理和静态代理有什么区别?举例说明。

  • 请解释CGLIB代理的原理。
    CGLIB(Code Generation Library)是一个功能强大的代码生成库,用于在运行时生成字节码并创建代理对象。CGLIB代理是一种基于继承的动态代理方式,与基于接口的动态代理(如JDK动态代理)不同。

    CGLIB代理的原理是通过继承目标类并重写其方法来创建代理对象。当使用CGLIB代理时,CGLIB会在运行时动态生成一个新的类,该类继承自目标类,并在其中重写需要代理的方法,并在重写的方法中调用被代理类的super方法。这样可以保证代理类在执行代理方法时能够调用到被代理类的原始实现。

    例如,如果被代理类有一个方法叫做doSomething(),那么CGLIB代理会生成一个子类,并在子类中重写doSomething()方法。在重写的方法中,会先调用被代理类的super.doSomething(),然后再执行代理逻辑。这样就能够保证代理类在执行代理方法时能够调用到被代理类的原始实现。然后,通过调用这个新生成的类的实例来实现代理功能。

    相比于基于接口的动态代理,CGLIB代理可以代理没有实现接口的类,也可以代理类的final方法。但是,由于CGLIB是通过生成子类来实现代理的,所以无法代理final类。

  • CGLIB代理和JDK动态代理有什么区别?举例说明。
    JDK动态代理是通过Java反射机制实现的,它要求被代理的类必须实现一个或多个接口。在运行时,JDK动态代理会动态生成一个实现了代理接口的代理类,并在代理类的方法中调用InvocationHandler接口的invoke方法来实现代理逻辑。
    CGLIB代理是通过继承目标类来实现的,它不要求目标类实现接口。在运行时,CGLIB会动态生成一个目标类的子类,并重写目标类的方法来实现代理逻辑。

jdk代理

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;public class ServiceProxyHandler implements InvocationHandler {private Object target;public ServiceProxyHandler(Object target) {this.target = target;}@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {Object result = null;if (method.getName().equals("save")||method.getName().equals("update")){try {System.out.println(method.getName()+"事务执行前");result= method.invoke(target, args);System.out.println(method.getName()+"事务执行后");} catch (Exception e) {throw new RuntimeException("操作执行失败,事务回滚");} finally {System.out.println("后置通知");}return result;}else {return method.invoke(target, args);}}
}
/*** JDK代理是对接口的代理,适用于只实现了接口的类*/
public class TestJDKProxy {public static void main(String[] args) {BookService bookService = new BookServiceImpl();ServiceProxyHandler userServiceProxyHandler = new ServiceProxyHandler(bookService);BookService o = (BookService) Proxy.newProxyInstance(bookService.getClass().getClassLoader(),bookService.getClass().getInterfaces(), userServiceProxyHandler);o.save();System.out.println();o.select();System.out.println();o.update();}
}

Cgclib代理

import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;import java.lang.reflect.Method;public class MyInterceptor implements MethodInterceptor {/*** 1. Object o: 这个参数表示被代理的对象。* 2. Method method: 这个参数表示正在被调用的方法。* 3. Object[] objects: 这个参数是一个包含被调用方法的参数的数组。* 4. MethodProxy methodProxy: 这个参数是用于调用原始方法的代理对象。*/@Overridepublic Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) {Object result = null;if (method.getName().equals("save")||method.getName().equals("update")||method.getName().equals("delete")){try {System.out.println("前置通知");result = methodProxy.invokeSuper(o, objects);System.out.println("事务处理完成");} catch (Throwable throwable) {System.out.println("事务异常,回滚事务!");throwable.printStackTrace();} finally {System.out.println("后置通知");}}else{try {result = methodProxy.invokeSuper(o, objects);} catch (Throwable throwable) {throwable.printStackTrace();}}return result;}
}
import edu.lzlg.proxy.service.impl.BookServiceImpl;
import net.sf.cglib.proxy.Enhancer;/*** CGCLIB代理是对类的代理,所以可以适用于类独有的方法*/
public class TestCGCLIB {public static void main(String[] args) {Enhancer enhancer = new Enhancer();enhancer.setSuperclass(BookServiceImpl.class);enhancer.setCallback(new MyInterceptor());BookServiceImpl bookService = (BookServiceImpl) enhancer.create();bookService.save();System.out.println();bookService.update();System.out.println();bookService.select();System.out.println();bookService.delete();}
}

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 驱动开发系列18 - PAGE_SHIFT 解释
  • Golang | Leetcode Golang题解之第438题找到字符串中所有字母异位词
  • 智能监控,守护绿色能源:EasyCVR在电站视频监控中心的一站式解决方案
  • 华为GaussDB数据库(单机版)在ARM环境下的安装指南
  • 【C++笔试强训】如何成为算法糕手Day5
  • Html jquery下拉select美化插件——selectFilter.js
  • 街头摊贩检测系统源码分享
  • 微信小程序showLoading ,showToast ,hideLoading连续调用出现showLoading 不关闭的情况记录
  • Linux云计算 |【第四阶段】NOSQL-DAY2
  • 了解针对基座大语言模型(类似 ChatGPT 的架构,Decoder-only)的重头预训练和微调训练
  • SpringCloud 2023各依赖版本选择、核心功能与组件、创建项目(注意事项、依赖)
  • Redis一些简单通用命令认识常用数据类型和编码方式认识Redis单线程模型
  • 【Python-GUI图形化界面-PyQt5模块(3)】——Qwidget核心模块
  • Django项目配置日志
  • 【重学 MySQL】四十、SQL 语句执行过程
  • [ 一起学React系列 -- 8 ] React中的文件上传
  • [Vue CLI 3] 配置解析之 css.extract
  • 【译】理解JavaScript:new 关键字
  • Babel配置的不完全指南
  • django开发-定时任务的使用
  • Hibernate【inverse和cascade属性】知识要点
  • JavaScript 奇技淫巧
  • JS题目及答案整理
  • macOS 中 shell 创建文件夹及文件并 VS Code 打开
  • Mithril.js 入门介绍
  • Nodejs和JavaWeb协助开发
  • Unix命令
  • 规范化安全开发 KOA 手脚架
  • 回流、重绘及其优化
  • 基于 Babel 的 npm 包最小化设置
  • 浏览器缓存机制分析
  • 爬虫进阶 -- 神级程序员:让你的爬虫就像人类的用户行为!
  • 前端技术周刊 2018-12-10:前端自动化测试
  • 嵌入式文件系统
  • 使用 @font-face
  • 视频flv转mp4最快的几种方法(就是不用格式工厂)
  • 微信小程序上拉加载:onReachBottom详解+设置触发距离
  • 小程序测试方案初探
  • ​渐进式Web应用PWA的未来
  • "无招胜有招"nbsp;史上最全的互…
  • #include
  • #我与Java虚拟机的故事#连载18:JAVA成长之路
  • $con= MySQL有关填空题_2015年计算机二级考试《MySQL》提高练习题(10)
  • (2)(2.4) TerraRanger Tower/Tower EVO(360度)
  • (delphi11最新学习资料) Object Pascal 学习笔记---第14章泛型第2节(泛型类的类构造函数)
  • (poj1.2.1)1970(筛选法模拟)
  • (Redis使用系列) Springboot 使用redis实现接口幂等性拦截 十一
  • (顶刊)一个基于分类代理模型的超多目标优化算法
  • (二)Optional
  • (二)springcloud实战之config配置中心
  • (附源码)springboot家庭财务分析系统 毕业设计641323
  • (三)Honghu Cloud云架构一定时调度平台
  • (使用vite搭建vue3项目(vite + vue3 + vue router + pinia + element plus))
  • (算法)求1到1亿间的质数或素数
  • (淘宝无限适配)手机端rem布局详解(转载非原创)