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

高级java每日一道面试题-2024年9月18日-设计模式篇-JDK动态代理,CGLIB代理,AspectJ区别?

如果有遗漏,评论区告诉我进行补充

面试官: JDK动态代理,CGLIB代理,AspectJ区别?

我回答:

在Java开发中,代理(Proxy)是一种常用的设计模式,它允许开发者在不修改原有类代码的情况下,通过代理类来控制对原有类的访问,并可以添加额外的功能。Java提供了几种实现代理的方式,包括JDK动态代理、CGLIB代理和AspectJ(虽然AspectJ更多用于面向切面编程,但也可以看作是一种代理技术)。下面分别详细解释这三种代理技术。

1. JDK动态代理

原理:
  • JDK动态代理主要利用java.lang.reflect.Proxy类和java.lang.reflect.InvocationHandler接口来实现。它只能代理实现了接口的类。
使用场景
  • 当目标对象实现了至少一个接口时。
  • 需要对方法进行拦截和增强,但不需要修改原始代码。
步骤:
  1. 定义接口:定义业务逻辑接口。
  2. 实现接口:编写具体的业务逻辑实现类。
  3. 创建代理类:使用Proxy.newProxyInstance()方法创建代理实例,需要提供三个参数:
    • 类加载器(ClassLoader
    • 代理类实现的接口列表
    • InvocationHandler实例
  4. 实现InvocationHandler接口:在这个接口的invoke方法中编写代理逻辑。
优点:
  • 简单易用,不需要修改原有类的代码。
  • 代理类是基于接口的,因此具有更好的解耦性。
缺点:
  • 只能代理实现了接口的类。
  • 相对于CGLIB,性能稍差(因为是通过反射实现的)。

2. CGLIB代理

原理:
  • CGLIB(Code Generation Library)是一个强大的、高性能的代码生成库,它可以在运行时扩展Java类和实现接口。CGLIB通过继承被代理的类来创建动态代理。
使用场景
  • 当目标对象没有实现任何接口时。
  • 需要对方法进行拦截和增强,但不需要修改原始代码。
步骤:
  1. 引入CGLIB库。
  2. 创建一个实现了MethodInterceptor接口的类,并重写intercept方法。
  3. 使用Enhancer类来创建代理对象,需要设置父类(即被代理的类)和MethodInterceptor实例。
优点:
  • 可以代理没有实现接口的类。
  • 性能比JDK动态代理好(因为是通过继承实现的,避免了反射的开销)。
缺点:
  • 由于是通过继承实现的,因此不能代理final类。
  • 增加了类的复杂度,因为会生成大量的类文件。生成的代理类数量较多,可能会增加内存开销。

3. AspectJ

原理:

AspectJ是一个全面的AOP框架,提供了比Spring AOP更强大的AOP功能。AspectJ支持多种类型的切面,包括基于方法的、基于构造函数的、基于字段的等。AspectJ可以在编译时、类加载时或运行时织入切面。

使用场景
  • 需要全面的AOP支持,包括对方法、构造函数、字段等的切面。
  • 需要在编译时、类加载时或运行时织入切面。
实现方式
  • 编译时织入:使用AspectJ编译器(ajc)在编译阶段织入切面。
  • 类加载时织入:使用AspectJ的LTW(Load-Time Weaving)功能,在类加载时织入切面。
  • 运行时织入:使用AspectJ的RTW(Runtime Weaving)功能,在运行时织入切面。
优点:
  • 提供了全面的AOP支持。
  • 支持多种织入时机,灵活性高。
  • 性能较好,尤其是在编译时织入的情况下。
缺点:
  • 学习曲线较陡峭。
  • 需要引入额外的工具和配置。
  • 在某些情况下可能会影响代码的可读性和维护性。

总结

  • JDK动态代理适用于目标类实现了接口的情况,简单易用,但只能代理实现了接口的类。
  • CGLIB代理适用于目标类没有实现接口的情况,性能较好,但需要引入额外的库,并且不能代理final类或final方法。
  • AspectJ提供了最全面的AOP支持,适用于复杂的AOP需求,支持多种织入时机,但学习成本较高,配置也相对复杂。

在面试中,能够清晰地解释这三种代理机制的工作原理、适用场景以及各自的优缺点,将有助于展示你对AOP技术和代理模式的深入理解。此外,实际项目经验也是面试官非常看重的部分,因此准备好相关的项目案例来说明你的实践经历也是非常有帮助的。

相关文章:

  • MySQL数据库迁移与备份实录
  • 如何在O2OA中使用ElementUI组件进行审批流程工作表单设计
  • 重生之我在代码随想录刷算法第十四天 | 513.找树左下角的值、112. 路径总和、106.从中序与后序遍历序列构造二叉树
  • mysql-connector-java本地试验
  • Python数据分析工具(三):pymssql的用法
  • 选对工具,效率飞跃提升
  • Kibana中突然看不到日志ElasticSearch突然采集不到日志问题解决分析
  • Ubuntu24.04 安装ssh开启22端口及允许root用户远程登录
  • 记录一次学习--委派攻击学习
  • Ubuntu以及ROS的一些方便设置及使用
  • H.264与H.265
  • Protobuf vs Thrift: 高性能序列化框架的对比与分析
  • 消息队列常见面试题总结
  • Linux复习--系统管理类(权限优化、备份策略、RAID、资源查看、启动流程、系统优化)
  • 灵当CRM index.php接口SQL注入漏洞复现 [附POC]
  • “大数据应用场景”之隔壁老王(连载四)
  • CSS实用技巧
  • Flex布局到底解决了什么问题
  • Java小白进阶笔记(3)-初级面向对象
  • Js基础——数据类型之Null和Undefined
  • JWT究竟是什么呢?
  • Odoo domain写法及运用
  • Puppeteer:浏览器控制器
  • SpiderData 2019年2月16日 DApp数据排行榜
  • vue数据传递--我有特殊的实现技巧
  • Wamp集成环境 添加PHP的新版本
  • 阿里研究院入选中国企业智库系统影响力榜
  • 好的网址,关于.net 4.0 ,vs 2010
  • 精彩代码 vue.js
  • 如何正确配置 Ubuntu 14.04 服务器?
  • 微信小程序:实现悬浮返回和分享按钮
  • ​LeetCode解法汇总1276. 不浪费原料的汉堡制作方案
  • #70结构体案例1(导师,学生,成绩)
  • #etcd#安装时出错
  • (03)光刻——半导体电路的绘制
  • (1)(1.13) SiK无线电高级配置(六)
  • (1)STL算法之遍历容器
  • (C语言)深入理解指针2之野指针与传值与传址与assert断言
  • (Matlab)使用竞争神经网络实现数据聚类
  • (vue)el-cascader级联选择器按勾选的顺序传值,摆脱层级约束
  • (附源码)springboot 基于HTML5的个人网页的网站设计与实现 毕业设计 031623
  • (附源码)springboot掌上博客系统 毕业设计063131
  • (附源码)计算机毕业设计SSM教师教学质量评价系统
  • (六)激光线扫描-三维重建
  • (强烈推荐)移动端音视频从零到上手(上)
  • (五)关系数据库标准语言SQL
  • (一)【Jmeter】JDK及Jmeter的安装部署及简单配置
  • (一)使用Mybatis实现在student数据库中插入一个学生信息
  • (已解决)Bootstrap精美弹出框模态框modal,实现js向modal传递数据
  • ****** 二 ******、软设笔记【数据结构】-KMP算法、树、二叉树
  • . ./ bash dash source 这五种执行shell脚本方式 区别
  • .NET “底层”异步编程模式——异步编程模型(Asynchronous Programming Model,APM)...
  • .NET 使用 ILRepack 合并多个程序集(替代 ILMerge),避免引入额外的依赖
  • .NET/C# 项目如何优雅地设置条件编译符号?
  • .NET/C# 异常处理:写一个空的 try 块代码,而把重要代码写到 finally 中(Constrained Execution Regions)