Spring boot 项目 Spring 注入 代理 并支持 代理对象使用 @Autowired 去调用其他服务

文章目录
- 类定义与依赖注入
- 方法解析
- createCglibProxy
- 注意事项
- setApplicationContext 方法
- createCglibProxy 方法
类定义与依赖注入
- @Service: 标识这是一个 Spring 管理的服务类。
- ApplicationContextAware: 实现该接口允许你在类中获取 ApplicationContext 对象,从而可以访问 Spring 容器中的所有 Bean。
- @Autowired: 注入了 AutowireCapableBeanFactory,用于自动装配新创建的代理对象。
方法解析
- invokeSendMessage
- 此方法接收一个类名(对应于某个实现了 DeviceMessageInterface 的 Bean)和一个 SendMessage 对象作为参数。它首先通过 applicationContext.getBean() 获取目标 Bean 的实例,然后创建该实例的 CGLIB 代理,并调用代理的 sendMessage 方法。
- invokeAllSendMessages
- 遍历所有实现了 DeviceMessageInterface 接口的 Bean,并对每个 Bean 创建其 CGLIB 代理对象,随后调用代理的 sendMessage 方法。这使得你可以一次性对所有相关处理器发送消息。
- invokeReceiveMessage
- 类似于 invokeAllSendMessages,但它是为处理接收到的消息而设计的。它会尝试调用每个处理器的 receiveMessage 方法,并返回第一个非空的结果(如果有的话)。如果所有处理器都未能成功处理消息,则返回一个包含错误信息的 JSON 对象。
createCglibProxy
这是一个泛型方法,负责创建给定类的 CGLIB 代理。代理对象在调用任何方法时都会先打印出方法名称,执行完方法后再打印一次。此外,它还会使用 autowireCapableBeanFactory.autowireBean(proxyInstance) 来确保代理对象能够被正确地注入依赖。
注意事项
线程池未使用:虽然代码中注释掉了 ThreadPoolTaskExecutor taskExecutor,但如果你希望异步执行这些操作,可以考虑取消注释并利用线程池来并发处理任务。
异常处理:目前 invokeReceiveMessage 和 invokeAllSendMessages 中的异常只是简单地打印堆栈跟踪。根据你的需求,可能需要更复杂的错误处理逻辑。
CountDownLatch 未使用:你声明了 CountDownLatch countDownLatch 但没有实际使用它。如果你打算用于同步操作,请确保正确初始化并在适当的地方使用它。
JSON 异常处理:在构造返回的 JSON 对象时捕获了 JSONException,但实际上在这个上下文中不太可能发生此类异常,因为 put 方法不会抛出受检异常。
setApplicationContext 方法
setApplicationContext 方法实现了 ApplicationContextAware 接口中的方法,用于设置当前的 ApplicationContext。这个方法在 Spring 容器初始化时自动调用,允许你的类获取对整个应用上下文的访问权限。这对于需要直接与 Spring 容器交互或获取其他 Bean 的组件非常有用。
createCglibProxy 方法
createCglibProxy 方法使用了 CGLIB 库来创建一个给定类的代理对象,并且在方法调用前后打印日志信息。此外,它还使用了 Spring 的 AutowireCapableBeanFactory 来自动装配新创建的代理对象,确保它可以访问其他 Spring 管理的 Bean。
public <T> T createCglibProxy(Class<T> targetClass, String beanName) {Enhancer enhancer = new Enhancer();enhancer.setSuperclass(targetClass);enhancer.setCallback(new MethodInterceptor() {@Overridepublic Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {System.out.println("Before method: " + method.getName());Object result = proxy.invokeSuper(obj, args);System.out.println("After method: " + method.getName());return result;}});T proxyInstance = (T) enhancer.create();autowireCapableBeanFactory.autowireBean(proxyInstance);return proxyInstance;
}
public <T> T createCglibProxy(Class<T> targetClass, String beanName) {
泛型方法声明:<T> 表示这是一个泛型方法,返回类型为 T。
参数:
- targetClass: 目标类的 Class 对象,用于指定要代理的类。
- beanName: 字符串类型的参数,代表目标 Bean 的名称(虽然在这个方法中没有直接使用)。
Enhancer enhancer = new Enhancer();
- 创建 CGLIB 的 Enhancer 实例:Enhancer 是 CGLIB 中用来生成子类或代理类的核心类。
enhancer.setSuperclass(targetClass);
- 设置父类:告诉 Enhancer 使用 targetClass 作为代理类的父类。这意味着代理类将继承 targetClass 的所有非私有方法。
enhancer.setCallback(new MethodInterceptor() {@Overridepublic Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {System.out.println("Before method: " + method.getName());Object result = proxy.invokeSuper(obj, args);System.out.println("After method: " + method.getName());return result;}
});
- 设置回调接口:MethodInterceptor 是 CGLIB 提供的一个接口,允许你在方法调用时插入自定义逻辑。这里通过匿名内部类实现了该接口。
intercept 方法:- obj: 被代理的对象实例。
- method: 当前被拦截的方法。
- args: 方法参数列表。
- proxy: MethodProxy 对象,提供了对原始方法的访问。
- 日志记录:在调用实际方法之前和之后分别打印一条消息。
- 调用父类方法:proxy.invokeSuper(obj, args) 调用了原始类的方法实现。
- 返回结果:将原始方法的结果返回给调用者。
T proxyInstance = (T) enhancer.create();
- 创建代理实例:enhancer.create() 方法根据配置创建并返回一个新的代理实例。这里强制转换为 T 类型,确保返回值与输入参数 targetClass 的类型一致。
autowireCapableBeanFactory.autowireBean(proxyInstance);
- 自动装配依赖:使用 Spring 的 AutowireCapableBeanFactory 对代理实例进行自动装配,这一步骤使得代理对象能够像普通的 Spring Bean 一样获得依赖注入。
return proxyInstance;
- 返回代理对象:最终返回创建好的代理对象,供调用方使用。
import org.json.JSONException;
import org.json.JSONObject;
import org.nuobeifu.dataprocessing.devicemessage.DeviceMessageInterface;
import org.nuobeifu.dataprocessing.devicemessage.entity.ReceiveMessage;
import org.nuobeifu.dataprocessing.devicemessage.entity.SendMessage;
import org.nuobeifu.dataprocessing.entity.vo.SysDeviceMessageExecuteTaskVO;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;
import java.lang.reflect.Method;
import java.util.Map;
import java.util.concurrent.CountDownLatch;@Service
public class CglibProxyService implements ApplicationContextAware {private ApplicationContext applicationContext;@Autowiredprivate AutowireCapableBeanFactory autowireCapableBeanFactory;// @Autowired
// private ThreadPoolTaskExecutor taskExecutor;private CountDownLatch countDownLatch;@Overridepublic void setApplicationContext(ApplicationContext applicationContext) throws BeansException {this.applicationContext = applicationContext;this.autowireCapableBeanFactory = applicationContext.getAutowireCapableBeanFactory();}public void invokeSendMessage(String className, SendMessage taskvo) {// 获取 Bean 实例DeviceMessageInterface instance = applicationContext.getBean(className, DeviceMessageInterface.class);// 创建 CGLIB 代理对象DeviceMessageInterface proxyInstance = createCglibProxy(instance.getClass(), className);// 调用 sendMessage 方法proxyInstance.sendMessage(taskvo);}public void invokeAllSendMessages(SendMessage taskvo) {try {// 获取所有实现 DeviceMessageInterface 的 BeanMap<String, DeviceMessageInterface> beans = applicationContext.getBeansOfType(DeviceMessageInterface.class);for (Map.Entry<String, DeviceMessageInterface> entry : beans.entrySet()) {String beanName = entry.getKey();DeviceMessageInterface instance = entry.getValue();// 创建 CGLIB 代理对象DeviceMessageInterface proxyInstance = createCglibProxy(instance.getClass(), beanName);// 调用 sendMessage 方法proxyInstance.sendMessage(taskvo);}} catch (Exception e) {e.printStackTrace();}}public JSONObject invokeReceiveMessage(String className, ReceiveMessage taskvo) {try {// 获取所有实现 DeviceMessageInterface 的 BeanMap<String, DeviceMessageInterface> beans = applicationContext.getBeansOfType(DeviceMessageInterface.class);for (Map.Entry<String, DeviceMessageInterface> entry : beans.entrySet()) {String beanName = entry.getKey();DeviceMessageInterface instance = entry.getValue();// 创建 CGLIB 代理对象DeviceMessageInterface proxyInstance = createCglibProxy(instance.getClass(), beanName);// 调用 sendMessage 方法JSONObject jsonObject = proxyInstance.receiveMessage(taskvo);return jsonObject;}} catch (Exception e) {e.printStackTrace();}JSONObject jsonObject = new JSONObject();try{jsonObject.put("msg", "信息异常");}catch (JSONException ex){}return jsonObject;}public <T> T createCglibProxy(Class<T> targetClass, String beanName) {Enhancer enhancer = new Enhancer();enhancer.setSuperclass(targetClass);enhancer.setCallback(new MethodInterceptor() {@Overridepublic Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {System.out.println("Before method: " + method.getName());Object result = proxy.invokeSuper(obj, args);System.out.println("After method: " + method.getName());return result;}});T proxyInstance = (T) enhancer.create();autowireCapableBeanFactory.autowireBean(proxyInstance);return proxyInstance;}}
相关文章:
Spring boot 项目 Spring 注入 代理 并支持 代理对象使用 @Autowired 去调用其他服务
文章目录 类定义与依赖注入方法解析createCglibProxy注意事项setApplicationContext 方法createCglibProxy 方法 类定义与依赖注入 Service: 标识这是一个 Spring 管理的服务类。ApplicationContextAware: 实现该接口允许你在类中获取 ApplicationContext 对象,从而…...
Colyseus 与 HTTP API 的集成
Colyseus 与 HTTP API 的集成 在使用 Colyseus 开发实时多人应用时,通常需要与传统的 HTTP API 集成,例如用户身份验证、存储游戏数据、获取排行榜等。以下是 Colyseus 与 HTTP API 集成的详细介绍: 1. Colyseus 的基本架构 Colyseus 是一个…...
基于服务器部署的综合视频安防系统的智慧快消开源了。
智慧快消视频监控平台是一款功能强大且简单易用的实时算法视频监控系统。它的愿景是最底层打通各大芯片厂商相互间的壁垒,省去繁琐重复的适配流程,实现芯片、算法、应用的全流程组合,从而大大减少企业级应用约95%的开发成本。国产化人工智能“…...
SpringBoot原理分析-1
SpringBoot原理分析 作为一个javaer,和boot打交道是很常见的吧。熟悉boot的人都会知道,启动一个springboot应用,就是用鼠标点一下启动main方法,然后等着就行了。我们来看看这个main里面。 SpringBootApplication public class E…...
HCIA-Access V2.5_7_5_XG(S)- GPON网络演进为XG(S)-PON网络
目前由于10 GPON ONU数量并没有得到大规模爆发,所以直接新建ODN网络成本相对较高,所以可以采用复用ODN的方案。 XG(S)-PON可以与GPON共享ODN 前面也介绍过GPON和10G GPON使用的波长,我们来回顾一下,在GPON网络中上行采用1310纳米波长,下行采用1490纳米的波长,而10G GPON…...
GPU算力平台的应用之任意门:任意穿搭匹配模型的应用教程
大家好,今天给大家介绍一下:GPU算力平台的应用之任意门:任意穿搭匹配模型的应用教程。 文章目录 一、GPU算力平台概述人工智能智能发展为什么需要GPU算力平台 二、注册与登录账号注册流程 三、平台的应用之Anydoor应用启动器选择Anydoor的应用场景Anydoo…...
如何利用人工智能算法优化知识分类和标签?
如何利用人工智能算法优化知识分类和标签? 聚类算法 原理与应用: 聚类算法是一种无监督学习算法,它可以根据数据的相似性将知识内容自动划分成不同的类别。例如,在文档知识库中,通过对文档内容的词向量表示应用 K -…...
Windows 11 系统中npm-cache优化
在 Windows 11 系统中,C:\Users\K\AppData\Local\npm-cache 文件夹是 npm(Node Package Manager) 用于缓存已下载的包的目录。缓存的存在可以加快包的安装速度,因为当再次安装相同的包时,npm 可以直接从缓存中获取&…...
Flink使用
Window下启动支持 下载或复制老版本的放在bin目录下即可; flink.bat echo off setlocalSET bin%~dp0 SET FLINK_HOME%bin%.. SET FLINK_LIB_DIR%FLINK_HOME%\lib SET FLINK_PLUGINS_DIR%FLINK_HOME%\pluginsSET JVM_ARGS-Xmx512mSET FLINK_JM_CLASSPATH%FLINK_LI…...
简易屏幕共享工具-基于WebSocket
前面写了两个简单的屏幕共享工具,不过那只是为了验证通过截屏的方式是否可行,因为通常手动截屏的频率很低,而对于视频来说它的帧率要求就很高了,至少要一秒30帧率左右。所以,经过实际的截屏工具验证,我了解…...
Redis——主从复制模式
文章目录 1. 引入2. 主从复制模式2.1 概念2.2 配置2.3 原理2.3.1 建立连接阶段2.3.2 命令传播阶段2.3.3 心跳检测机制2.3.4 部分重同步机制(1) 主节点通过 复制积压缓冲区 记录写命令(2) 主节点通过 复制偏移量 判断从节点是否满足执行部分重同步的条件(3) 执行部分重同步操作 …...
简历_熟悉缓存高并发场景处理方法,如缓存穿透、缓存击穿、缓存雪崩
系列博客目录 文章目录 系列博客目录1.缓存穿透总结 2.缓存雪崩3.缓存击穿代码总结 1.缓存穿透 缓存穿透是指客户端请求的数据在缓存中和数据库中都不存在,这样缓存永远不会生效,这些请求都会打到数据库。 常见的解决方案有两种: 缓存空对…...
阿里云电商平台用户行为分析与人群画像系统设计与实现
通过在阿里云(https://baike.baidu.com/item/%E9%98%BF%E9%87%8C%E4%BA%91/297128)上构建包含数据源层、数据存储层、数据处理层、数据分析层和数据应用层的系统架构,并设计合理的数据模型、ETL流程、数据质量与性能监控机制以及安全与合规性…...
Go语言的 的输入/输出流(I/O Streams)核心知识
Go语言的输入/输出流(I/O Streams)核心知识 前言 Go语言是一种现代编程语言,因其高效性、简洁性及强大的并发支持而受到开发者的喜爱。在开发应用程序时,输入/输出(I/O)操作是一个不可或缺的部分。无论是…...
57.在 Vue 3 中使用 OpenLayers 点击选择 Feature 设置特定颜色
在 Web 开发中,地图应用是非常常见的需求,而 OpenLayers 是一个非常强大的地图库,它提供了丰富的地图操作功能。今天,我们将一起学习如何在 Vue 3 中结合 OpenLayers 使用点击事件来选择地图上的 Feature,并设置特定的…...
数据结构C语言描述8(图文结合)--哈希、哈希冲突、开放地址法、链地址法等实现
前言 这个专栏将会用纯C实现常用的数据结构和简单的算法;有C基础即可跟着学习,代码均可运行;准备考研的也可跟着写,个人感觉,如果时间充裕,手写一遍比看书、刷题管用很多,这也是本人采用纯C语言…...
自动化立体库安全使用管理制度完整版
导语 大家好,我是社长,老K。专注分享智能制造和智能仓储物流等内容。欢迎大家到本文底部评论区留言。 新书《智能物流系统构成与技术实践》人俱乐部 完整版文件和更多学习资料,请球友到知识星球【智能仓储物流技术研习社】自行下载。 以下是《…...
云打印之拼多多打印组件交互协议
拼多多打印组件交互协议相关介绍如下: 1、打印组件下载地址 http://meta.pinduoduo.com/api/one/app/v1/lateststable?appIdcom.xunmeng.pddprint&platformwindows&subTypemain 2、socket连接端口 如果是http的话,端口是5000 socket new …...
TCP 演进之路:软硬件跷跷板与新征程
今天依旧是与 TCP 相关的一个短评。 先看软硬件间的胶着。晶体管诞生以来,硬件一直在突飞猛进发展,后来这个事被摩尔定律正则化,人们开始可以预测未来,但即便如此,软件依然跟不上来,不过几年,老…...
React最小状态管理Jotai
Jotai 状态管理 1. 简介 Jotai 是一个基于原子 atom 概念的 React 状态管理库,它提供了简单且灵活的方式来管理应用状态, 而且非常轻量, 大厂用的非常多。 JotaiRedux适合单个页面,多次用到的属性适合全局公共属性超级轻量(与use…...
【Python】 -- 趣味代码 - 小恐龙游戏
文章目录 文章目录 00 小恐龙游戏程序设计框架代码结构和功能游戏流程总结01 小恐龙游戏程序设计02 百度网盘地址00 小恐龙游戏程序设计框架 这段代码是一个基于 Pygame 的简易跑酷游戏的完整实现,玩家控制一个角色(龙)躲避障碍物(仙人掌和乌鸦)。以下是代码的详细介绍:…...
linux之kylin系统nginx的安装
一、nginx的作用 1.可做高性能的web服务器 直接处理静态资源(HTML/CSS/图片等),响应速度远超传统服务器类似apache支持高并发连接 2.反向代理服务器 隐藏后端服务器IP地址,提高安全性 3.负载均衡服务器 支持多种策略分发流量…...
Java 8 Stream API 入门到实践详解
一、告别 for 循环! 传统痛点: Java 8 之前,集合操作离不开冗长的 for 循环和匿名类。例如,过滤列表中的偶数: List<Integer> list Arrays.asList(1, 2, 3, 4, 5); List<Integer> evens new ArrayList…...
基于Flask实现的医疗保险欺诈识别监测模型
基于Flask实现的医疗保险欺诈识别监测模型 项目截图 项目简介 社会医疗保险是国家通过立法形式强制实施,由雇主和个人按一定比例缴纳保险费,建立社会医疗保险基金,支付雇员医疗费用的一种医疗保险制度, 它是促进社会文明和进步的…...
《Playwright:微软的自动化测试工具详解》
Playwright 简介:声明内容来自网络,将内容拼接整理出来的文档 Playwright 是微软开发的自动化测试工具,支持 Chrome、Firefox、Safari 等主流浏览器,提供多语言 API(Python、JavaScript、Java、.NET)。它的特点包括&a…...
抖音增长新引擎:品融电商,一站式全案代运营领跑者
抖音增长新引擎:品融电商,一站式全案代运营领跑者 在抖音这个日活超7亿的流量汪洋中,品牌如何破浪前行?自建团队成本高、效果难控;碎片化运营又难成合力——这正是许多企业面临的增长困局。品融电商以「抖音全案代运营…...
SpringBoot+uniapp 的 Champion 俱乐部微信小程序设计与实现,论文初版实现
摘要 本论文旨在设计并实现基于 SpringBoot 和 uniapp 的 Champion 俱乐部微信小程序,以满足俱乐部线上活动推广、会员管理、社交互动等需求。通过 SpringBoot 搭建后端服务,提供稳定高效的数据处理与业务逻辑支持;利用 uniapp 实现跨平台前…...
Springcloud:Eureka 高可用集群搭建实战(服务注册与发现的底层原理与避坑指南)
引言:为什么 Eureka 依然是存量系统的核心? 尽管 Nacos 等新注册中心崛起,但金融、电力等保守行业仍有大量系统运行在 Eureka 上。理解其高可用设计与自我保护机制,是保障分布式系统稳定的必修课。本文将手把手带你搭建生产级 Eur…...
从零实现STL哈希容器:unordered_map/unordered_set封装详解
本篇文章是对C学习的STL哈希容器自主实现部分的学习分享 希望也能为你带来些帮助~ 那咱们废话不多说,直接开始吧! 一、源码结构分析 1. SGISTL30实现剖析 // hash_set核心结构 template <class Value, class HashFcn, ...> class hash_set {ty…...
OPENCV形态学基础之二腐蚀
一.腐蚀的原理 (图1) 数学表达式:dst(x,y) erode(src(x,y)) min(x,y)src(xx,yy) 腐蚀也是图像形态学的基本功能之一,腐蚀跟膨胀属于反向操作,膨胀是把图像图像变大,而腐蚀就是把图像变小。腐蚀后的图像变小变暗淡。 腐蚀…...
