动态代理的两个使用方式(手动实现+SpringAOP实现)-Demo
一、手动实现
1、具体代码
package com.xch.proxy;/*** 具体业务接口** @author XuChenghe* @date 2023/8/18 15:09*/
public interface Star {/*** 唱歌方法** @param name* @return*/String sing(String name);/*** 跳舞方法*/void dance();}
package com.xch.proxy;/*** 具体业务实现类** @author XuChenghe* @date 2023/8/18 15:06*/
public class BigStar implements Star {private String userName;public BigStar(String userName) {this.userName = userName;}/*** {@inheritDoc}*/public String sing(String songName) {System.out.println(this.userName + "正在唱:" + songName);return "谢谢!谢谢!";}/*** {@inheritDoc}*/public void dance() {System.out.println(this.userName + "正在优美的跳舞~~");}}
package com.xch.proxy;import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;/*** 动态代理的工具类(产生代理的)* -手动实现原生动态代理** @author XuChenghe* @date 2023/8/18 15:11*/
public class ProxyUtil {public static Star createProxy(BigStar bigStar) {// 参数1:ClassLoader用于指定一个类加载器// 参数2:指定生成的代理有哪些方法// 参数3:用来指定生成的代理对象要干什么事情(动态代理的核心)Star starProxy = (Star) Proxy.newProxyInstance(ProxyUtil.class.getClassLoader(),new Class[]{Star.class}, new InvocationHandler() {// 回调方法@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {// 动态代理要做的事情,会在这里写代码if ("sing".equals(method.getName())) {System.out.println("准备话筒,收钱20万");} else if ("dance".equals(method.getName())) {System.out.println("准备场地,收钱100万");}return method.invoke(bigStar, args);}});return starProxy;}}
package com.xch.proxy;/*** 运行启动测试类** @author XuChenghe* @date 2023/8/18 15:21*/
public class LaunchTest {public static void main(String[] args) {Star starProxy = ProxyUtil.createProxy(new BigStar("杨超越"));String result = starProxy.sing("好日子");System.out.println(result);starProxy.dance();}}
二、SpringAOP实现
1、pom文件依赖
<!-- Spring的AOP切面编程启动环境依赖组 -->
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<!-- Spring的事务依赖 -->
<dependency><groupId>org.springframework</groupId><artifactId>spring-tx</artifactId>
</dependency>
2、具体代码
package com.xch.proxy_product;/*** 具体业务接口** @author XuChenghe* @date 2023/8/18 15:09*/
public interface Star {/*** 实际生产中使用的代理调用** @param name* @return*/String proxySing(String name);/*** 实际生产中使用的代理调用*/void proxyDance();}
package com.xch.proxy_product;import org.springframework.aop.framework.AopContext;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;/*** 具体业务实现类** @author XuChenghe* @date 2023/8/18 15:06*/
@Service
public class BigStar implements Star {/*** 唱歌方法** @param songName* @return*/@Transactional(rollbackFor = Exception.class)public String sing(String songName) {System.out.println("杨超越正在唱:" + songName);return "谢谢!谢谢!";}/*** 跳舞方法*/@Transactional(rollbackFor = Exception.class)public void dance() {System.out.println("杨超越正在优美的跳舞~~");}/*** {@inheritDoc}*/@Transactional(rollbackFor = Exception.class)public String proxySing(String songName) {System.out.println("准备话筒,收钱20万");return getCurrentProxy().sing("好日子");}/*** {@inheritDoc}*/@Transactional(rollbackFor = Exception.class)public void proxyDance() {System.out.println("准备场地,收钱100万");getCurrentProxy().dance();}/*** 获取当前类的代理** @return 当前类的代理*/private static BigStar getCurrentProxy() {return (BigStar) AopContext.currentProxy();}}
package com.xch.proxy_product;import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;/*** 通用业务的切面类** @author XuChenghe* @date 2023/8/20 8:55*/
@Aspect // 声明该类的作用:切面类
@Component // 等价于@Configuration:交由Spring的IOC容器管理
public class BigStarAspect {/*** 定义公共切入点* -假设proxy_product是service业务层包* -则通过以下表达式匹配该业务包下的所有子孙类的所有public修饰的方法** 另外,配置的切入表达式必须是符合public修饰的方法* 因为,Spring事务即AOP的底层通过动态代理生成代理调用该方法时,* 会判断方法只能是public修饰的Modifier.isPublic(method.getModifiers())*/@Pointcut("execution(public * com.xch.proxy_product..*(..))")public void myPointcut() {// 公共切入点}/*** 配置切面方法(环绕通知):方法增强** @param pjp 连接点:当前切入方法的信息* @return 方法执行的返回结果* @throws Throwable 方法执行时抛出的异常*/@Around("myPointcut()")public Object around(ProceedingJoinPoint pjp) throws Throwable {System.out.println("=====环绕通知(开始)=====");// 前置增强代码Object proceed = pjp.proceed();// 后置/返回增强代码// 最终增强代码// 抛出异常后增强代码System.out.println("=====环绕通知(结束)=====");return proceed;}
}
package com.xch;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.EnableAspectJAutoProxy;/*** 启用Spring的动态代理,默认使用JDK动态代理(由proxyTargetClass控制)*/
@SpringBootApplication
@EnableAspectJAutoProxy(exposeProxy = true)
public class SubDynamicProxyApplication {public static void main(String[] args) {SpringApplication.run(SubDynamicProxyApplication.class, args);}}
package com.xch.proxy_product;import org.junit.jupiter.api.Test;
import org.springframework.aop.support.AopUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;/*** 运行启动测试类** @author XuChenghe* @date 2023/8/18 15:21*/
@SpringBootTest
public class LaunchTest {@Autowiredprivate Star star;@Testpublic void launch() {String result = star.proxySing("好日子");System.out.println(result);System.out.println();star.proxyDance();// 判断该注入类是否代理类// -Spring的IOC容器中默认都是原生对象// -只有配置了AOP增强的对象才是代理对象System.out.println(AopUtils.isAopProxy(star));}}相关文章:
动态代理的两个使用方式(手动实现+SpringAOP实现)-Demo
一、手动实现 1、具体代码 package com.xch.proxy;/*** 具体业务接口** author XuChenghe* date 2023/8/18 15:09*/ public interface Star {/*** 唱歌方法** param name* return*/String sing(String name);/*** 跳舞方法*/void dance();} package com.xch.proxy;/*** 具体…...
面试话术(MQ+mybatis+nginx+redis+ssm+mysql+linux)
面试话术 RabbitMq1、介绍一下rabbitmq2、如何保证消息确定消息发送成功,并且被消费成功,有什么保障措施3、如何保证消息不被重复消费4、RabbitMQ 宕机了怎么处理 授权话术1、你给我说一下授权认证(登陆注册)的逻辑2、说一下jwt3、…...
JSON的理解
文章目录 1、什么是JSON2、为什么要用JSON3、JSON的格式规定3.1 对象(0bject):对应着JS中的对象3.2 数组(Array):对应着JS中的数组形式3.3 简单形式:对应着JS中的基础数据类型 4、JSON和Js的转换5、JSON对象…...
面试热题(二叉树的最大路径)
路径 被定义为一条从树中任意节点出发,沿父节点-子节点连接,达到任意节点的序列。同一个节点在一条路径序列中 至多出现一次 。该路径 至少包含一个 节点,且不一定经过根节点。 路径和 是路径中各节点值的总和。 给定一个二叉树的根节点 root…...
C#设计模式之--六大原则 开闭原则
设计模式六大原则是单一职责原则、里氏替换原则、依赖倒置原则、接口隔离原则、迪米特法则、开闭原则。它们不是要我们刻板的遵守,而是根据实际需要灵活运用。只要对它们的遵守程度在一个合理的范围内,努为做到一个良好的设计。本文主要介绍一下.NET(C#)…...
编写Dockerfile制作自己的镜像并推送到私有仓库
说明:我将用到的私有仓库是Harbor,安装教程参考我的这一篇文章: 安装搭建私有仓库Harbor_Word_Smith_的博客-CSDN博客 一、案例1 1、要求 编写Dockerfile制作Web应用系统nginx镜像,生成镜像nginx:v1.1,并推送其到私…...
华为OD-分积木/分苹果
题目描述 哥哥弟弟分一堆积木,每块积木重量不同。弟弟要求平分两组,每组数量可以不同但总重量必须相等。 然而弟弟只会二进制并且加法不进位。例如三块积木 3,5,6 分成两组 [3] 和 [5,6] 弟弟认为 5(二进制1001)加上6(…...
Mysql的引擎有哪些?支持事物么?DB储存引擎有哪些?
Mysql的引擎有哪些?支持事物么?DB储存引擎有哪些? MySQL有多种存储引擎,每种存储引擎有各自的优缺点,可以择优选择使用: MyISAM、InnoDB、MERGE、MEMORY(HEAP)、BDB(BerkeleyDB)、EXAMPLE、FEDERATED、ARCH…...
【懒加载】js实现懒加载、vue实现图片懒加载指令
懒加载 延迟加载,对于一个很长的页面,优先加载可视区域的内容,其他部分等进入可视区域时再加载 懒加载作用 是一种网页性能优化的方式,它能极大的提升用户体验。比如一个页面中有很多图片,但是首屏只出现几张&#…...
微信小程序教学系列(7)
第七章:小程序安全和权限管理 第一节:小程序安全性保障 在开发小程序时,我们要时刻牢记小程序的安全性。毕竟,我们可不希望我们的小程序被黑客入侵或者用户的隐私被泄露。所以,让我们一起来了解一下如何保障小程序的…...
Android 9.0 kenel和frameworks中修改ram运行内存的功能实现
1.前言 在9.0的系统rom产品开发定制中,在对一些产品开发中的配置需求方面,在产品后续订单中,在某些机型中需要升级下系统内核配置,项目时间比较仓促,所以 来不及对硬件重新定制,就需要软件方面在ram运行内存的容量大小方面作假,修改ram真实的大小容量,所以就需要在ken…...
PHP实践:获取网络上图片的长宽以及图片类型
🏆作者简介,黑夜开发者,全栈领域新星创作者✌,CSDN博客专家,阿里云社区专家博主,2023年6月CSDN上海赛道top4。 🏆数年电商行业从业经验,历任核心研发工程师,项目技术负责…...
使用 DPO 微调 Llama 2
简介 基于人类反馈的强化学习 (Reinforcement Learning from Human Feedback,RLHF) 事实上已成为 GPT-4 或 Claude 等 LLM 训练的最后一步,它可以确保语言模型的输出符合人类在闲聊或安全性等方面的期望。然而,它也给 NLP 引入了一些 RL 相关…...
数据库——事务,事务隔离级别
文章目录 什么是事务?事务的特性(ACID)并发事务带来的问题事务隔离级别实际情况演示脏读(读未提交)避免脏读(读已提交)不可重复读可重复读防止幻读(可串行化) 什么是事务? 事务是逻辑上的一组操作,要么都执行,要么都不执行。 事务最经典也经常被拿出…...
对《VB.NET通过VB6 ActiveX DLL调用PowerBasic及FreeBasic动态库》的改进
《VB.NET通过VB6 ActiveX DLL调用PowerBasic及FreeBasic动态库》使用的Activex DLL公共对象是需要先注册的。https://blog.csdn.net/weixin_45707491/article/details/132437502?spm1001.2014.3001.5501 Activex DLL事前注册,一次多用说起来也不是啥大问题&#x…...
【PHP】数据类型运算符位运算
文章目录 数据类型简单(基本)数据类型:4个小类复合数据类型:2个小类特殊数据类型:2个小类类型转换类型判断整数类型浮点类型布尔类型 运算符赋值运算符算术运算符比较运算符逻辑运算符连接运算符错误抑制符三目运算符自…...
使用 Nacos 作为 Spring Boot 配置中心
🌷🍁 博主猫头虎 带您 Go to New World.✨🍁 🦄 博客首页——猫头虎的博客🎐 🐳《面试题大全专栏》 文章图文并茂🦕生动形象🦖简单易学!欢迎大家来踩踩~🌺 &a…...
微服务 Eureka
Eureka Eureka是Netflix开源的一个用于构建基于微服务架构的服务发现和注册中心技术。在微服务架构中,系统被拆分成多个小型、自治的服务,每个服务负责特定的业务功能。这些服务需要能够相互发现和通信,这就是Eureka所提供的功能。 Eureka主…...
Spring Boot 事务和事务传播机制
1. 为什么需要事务? 事务定义 将一组操作封装成一个执行单元 (封装到一起),这一组的执行具备原子性, 那么就要么全部成功,要么全部失败. 为什么要用事务? 比如转账分为两个操作: 第一步操作:A 账户-100 元。 第二步操作:B账户 100 元。 如果没有事务&a…...
计算机组成原理(巨巨巨基础篇)
有关《计算机组成原理》课本中有关 内存计算换算(字,位,字节) 个人理解 前面知识点搭建框架,最后两道例题是直观理解体会 主存储器的基本概念 位:存储信息的最小单位,称为存储位或存储元。 背…...
C++:std::is_convertible
C++标志库中提供is_convertible,可以测试一种类型是否可以转换为另一只类型: template <class From, class To> struct is_convertible; 使用举例: #include <iostream> #include <string>using namespace std;struct A { }; struct B : A { };int main…...
Python爬虫实战:研究feedparser库相关技术
1. 引言 1.1 研究背景与意义 在当今信息爆炸的时代,互联网上存在着海量的信息资源。RSS(Really Simple Syndication)作为一种标准化的信息聚合技术,被广泛用于网站内容的发布和订阅。通过 RSS,用户可以方便地获取网站更新的内容,而无需频繁访问各个网站。 然而,互联网…...
Psychopy音频的使用
Psychopy音频的使用 本文主要解决以下问题: 指定音频引擎与设备;播放音频文件 本文所使用的环境: Python3.10 numpy2.2.6 psychopy2025.1.1 psychtoolbox3.0.19.14 一、音频配置 Psychopy文档链接为Sound - for audio playback — Psy…...
什么是EULA和DPA
文章目录 EULA(End User License Agreement)DPA(Data Protection Agreement)一、定义与背景二、核心内容三、法律效力与责任四、实际应用与意义 EULA(End User License Agreement) 定义: EULA即…...
企业如何增强终端安全?
在数字化转型加速的今天,企业的业务运行越来越依赖于终端设备。从员工的笔记本电脑、智能手机,到工厂里的物联网设备、智能传感器,这些终端构成了企业与外部世界连接的 “神经末梢”。然而,随着远程办公的常态化和设备接入的爆炸式…...
稳定币的深度剖析与展望
一、引言 在当今数字化浪潮席卷全球的时代,加密货币作为一种新兴的金融现象,正以前所未有的速度改变着我们对传统货币和金融体系的认知。然而,加密货币市场的高度波动性却成为了其广泛应用和普及的一大障碍。在这样的背景下,稳定…...
听写流程自动化实践,轻量级教育辅助
随着智能教育工具的发展,越来越多的传统学习方式正在被数字化、自动化所优化。听写作为语文、英语等学科中重要的基础训练形式,也迎来了更高效的解决方案。 这是一款轻量但功能强大的听写辅助工具。它是基于本地词库与可选在线语音引擎构建,…...
高效线程安全的单例模式:Python 中的懒加载与自定义初始化参数
高效线程安全的单例模式:Python 中的懒加载与自定义初始化参数 在软件开发中,单例模式(Singleton Pattern)是一种常见的设计模式,确保一个类仅有一个实例,并提供一个全局访问点。在多线程环境下,实现单例模式时需要注意线程安全问题,以防止多个线程同时创建实例,导致…...
省略号和可变参数模板
本文主要介绍如何展开可变参数的参数包 1.C语言的va_list展开可变参数 #include <iostream> #include <cstdarg>void printNumbers(int count, ...) {// 声明va_list类型的变量va_list args;// 使用va_start将可变参数写入变量argsva_start(args, count);for (in…...
Caliper 配置文件解析:fisco-bcos.json
config.yaml 文件 config.yaml 是 Caliper 的主配置文件,通常包含以下内容: test:name: fisco-bcos-test # 测试名称description: Performance test of FISCO-BCOS # 测试描述workers:type: local # 工作进程类型number: 5 # 工作进程数量monitor:type: - docker- pro…...
