【Spring】通过Spring收集自定义注解标识的方法
文章目录
- 前言
- 1. 声明注解
- 2. 使用 Spring 的工厂拓展
- 3. 收集策略
- 4. 完整的代码
- 后记
前言
需求:
用key找到对应的方法实现。使用注解的形式增量开发。
@MyComponent
public class Sample1 {@MyMethod(key = "key1")public String test2() {return "Shenzhen";}
}
任意时刻都能通过key来进行依赖查找
@Testpublic void test() {Assert.notNull(myBeanFactory.getMethod("key1"), "key1对应的方法不能为空");}
实现思路:
- 声明自己的类注解,并要求被 Spring 收集
- 声明自己的方法注解,确保可以通过反射获取
- 借 Spring 的能力,容器启动收集bean完成后,把bean列表交给自己,用于自己的收集策略。
1. 声明注解
- 类注解
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
// 继承Spring的注解,确保类能被Spring扫描
@Component
public @interface MyComponent {@AliasFor(annotation = Component.class)String value() default "";
}
- 方法注解
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface MyMethod {// 用于依赖查找的keyString key();
}
2. 使用 Spring 的工厂拓展
找到我们用注解标记的类、方法,Spring 收集完bean之后提供了拓展点供我们遍历这些bean。
- BeanFactoryPostProcessor 接口
- 其中 ConfigurableListableBeanFactory beanFactory 提供了容器
@Component
public class MyBeanFactory implements BeanFactoryPostProcessor {@Overridepublic void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {// 找到所有注解标记的beanMap<String, Object> beanMap = beanFactory.getBeansWithAnnotation(MyComponent.class);beanMap.forEach((beanName, bean) -> {// 收集bean中用注解标记的方法 (方法先省略)// collectMethod(bean);});}
}
3. 收集策略
- 收集策略可以很简单,这里就用一个Map收集
- 用Spring的AnnotationUtils.findAnnotation(method, MyMethod.class) 命中标识的方法
- 如果命中,则拿到注解中的key,收集key和Method的映射关系
// 自己的容器private static final Map<String, Method> METHOD_MAP = new HashMap<>();public Method getMethod(String key) {return METHOD_MAP.get(key);}private void collectMethod(Object bean) {Method[] methods = bean.getClass().getDeclaredMethods();Arrays.stream(methods)// 过滤: 只要MyMethod标识的方法 .filter(method -> Objects.nonNull(getAnnotation(method)))// 收集: 通过MyMethod的注解key,绑定依赖关系,放到自己的容器.forEach(method -> METHOD_MAP.putIfAbsent(getAnnotation(method).key(), method));}private static MyMethod getAnnotation(Method method) {return AnnotationUtils.findAnnotation(method, MyMethod.class);}
4. 完整的代码
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.stereotype.Component;import java.lang.reflect.Method;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;@Component
public class MyBeanFactory implements BeanFactoryPostProcessor {private static final ConcurrentHashMap<String, Method> METHOD_MAP = new ConcurrentHashMap<>();@Overridepublic void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {// 从Spring容器中获取所有MyControllerMap<String, Object> beanMap = beanFactory.getBeansWithAnnotation(MyComponent.class);beanMap.forEach((beanName, bean) -> {// 收集bean里面的所有可用方法collectMethod(bean);});}private void collectMethod(Object bean) {Method[] methods = bean.getClass().getDeclaredMethods();Arrays.stream(methods)// 过滤: 只要MyMethod标识的方法 .filter(method -> Objects.nonNull(getAnnotation(method)))// 收集: 通过MyMethod的注解key,绑定依赖关系,放到自己的容器.forEach(method -> METHOD_MAP.putIfAbsent(getAnnotation(method).key(), method));}private static MyMethod getAnnotation(Method method) {return AnnotationUtils.findAnnotation(method, MyMethod.class);}public Method getMethod(String key) {return METHOD_MAP.get(key);}
}
后记
记录下用到的 Spring 的 api 和工具
-
一个核心的接口方法获取bean容器
BeanFactoryPostProcessor#postProcessBeanFactory -
获取指定注解修饰的类
ConfigurableListableBeanFactory#getBeansWithAnnotation -
获取方法上的注解内容
AnnotationUtils#findAnnotation
相关文章:
【Spring】通过Spring收集自定义注解标识的方法
文章目录 前言1. 声明注解2. 使用 Spring 的工厂拓展3. 收集策略4. 完整的代码后记 前言 需求: 用key找到对应的方法实现。使用注解的形式增量开发。 MyComponent public class Sample1 {MyMethod(key "key1")public String test2() {return "She…...
基于深度学习的图书管理推荐系统(python版)
基于深度学习的图书管理推荐系统 1、效果图 1/1 [] - 0s 270ms/step [13 11 4 19 16 18 8 6 9 0] [0.1780757 0.17474999 0.17390694 0.17207369 0.17157653 0.168248440.1668652 0.16665359 0.16656876 0.16519257] keras_recommended_book_ids深度学习推荐列表 [9137…...
MATLAB 点云随机渲染赋色(51)
MATLAB 点云随机渲染赋色(51) 一、算法介绍二、算法实现1.代码2.效果总结一、算法介绍 为点云中的每个点随机赋予一种颜色,步骤和效果如图: 1、读取点云 (ply格式) 2、随机为每个点的RGB颜色字段赋值 3、保存结果 (ply格式) 二、算法实现 1.代码 代码如下(示例):…...
通过一篇文章让你完全掌握VS和电脑常用快捷键的使用方法
VS常用快捷键 前言一、 VS常用快捷键常用VS运行调试程序快捷键常用VS编辑程序快捷键 二、常用windows系统操作快捷键 前言 VS(Visual Studio)是一款强大的开发工具,提供了许多常用快捷键,以提高开发效率。这些快捷键包括文件操作…...
ChatGPT指引:借助ChatGPT撰写学术论文的技巧
ChatGPT无限次数:点击直达 ChatGPT指引:借助ChatGPT撰写学术论文的技巧 在当今信息技术高度发达的时代,人工智能技术的不断发展为学术研究者提供了更多的便利和可能。其中,自然语言处理技术中的ChatGPT无疑是一种强大的工具,它能…...
魔改一个过游戏保护的CE
csdn审核不通过 网易云课堂有配套的免费视频 int0x3 - 主页 文章都传到github了 Notes/外挂/魔改CE at master MrXiao7/Notes GitHub 为什么要编译自己的CE 在游戏逆向的过程中,很多游戏有保护,我们运行原版CE的时候会被检测到 比如我们开着CE运…...
rust嵌入式开发之await
嵌入式经常有类似通过串口发送指令然后等待响应再做出进一步反应的需求。比如,通过串口以AT命令来操作蓝牙模块执行扫描、连接,需要根据实际情况进行操作,复杂的可能需要执行7、8条指令才能完成连接。 对于这样的需求,如果用异步…...
UE4_碰撞_碰撞蓝图节点——Line Trace For Objects(对象的线条检测)
一、Line Trace For Objects(对象的线条检测):沿给定线条执行碰撞检测并返回遭遇的首个命中,这只会找到由Object types指定类型的对象。注意他与Line Trace By Channel(由通道检测线条)的区别,一个通过Obje…...
抽象类和接口的简单认识
目录 一、抽象类 1.什么是抽象类 2.抽象类的注意事项 3.抽象类与普通类的对比 二、接口 1.接口的简单使用 2.接口的特性 3.接口的使用案例 4.接口和抽象类的异同 一、抽象类 所谓抽象类,就是更加抽象的类,也就是说,这个类不能具体描…...
python-pytorch获取FashionMNIST实际图片标签数据集
在查看pytorch官方文档的时候,在这里链接中https://pytorch.org/tutorials/beginner/basics/data_tutorial.html的Creating a Custom Dataset for your files章节,有提到要自定义数据集,需要用到实际的图片和标签。 在网上找了半天没找到&a…...
深入探秘Python生成器:揭开神秘的面纱
一、问题起源: 想象一下,您掌握了一种魔法,在代码世界里,您可以轻松呼唤出一个整数。然而,事情并不总是看起来那样简单。在Python的奇妙王国中,我遇到了一个有趣的谜题: def tst():try:print(…...
红队攻防渗透技术实战流程:红队目标信息收集之批量信息收集
红队资产信息收集 1. 自动化信息收集1.1 自动化信息收集工具1.2 自动域名转换IP工具1.3 自动企业信息查询工具1.4 APP敏感信息扫描工具1.5 自动化信息工具的使用1.5.1 资产灯塔系统(ARL)1.5.1.1 docker环境安装1.2.2.9.1 水泽-信息收集自动化工具1. 自动化信息收集 1.1 自动化…...
【vue3学习笔记(二)】(第141-143节)初识setup;ref函数_处理基本类型;ref函数_处理对象类型
尚硅谷Vue2.0Vue3.0全套教程丨vuejs从入门到精通 本篇内容对应课程第141-143节 课程 P141节 《初识setup》笔记 1、setup是所有组合式API“表演的舞台”,组件中所用到的所有数据、方法、监视数据、生命周期钩子等都需要配置在setup中。 2、setup的两种返回值&…...
若依框架学习使用
若依官网项目拉取下来介绍 | RuoYi 项目运行: 1.idea安装,可以运行前后端 编辑器idea、jdk环境安装、数据库mysql、navicat工具、redis(redis-server启动)安装 2.navicat数据库连接, 创建数据库ry-vue并导入数据脚本ry_2021xxxx.sql,qua…...
蓝桥杯_数学模板
1.试除法判定质数 #include <iostream> using namespace std;bool is_zs(int x) {if(x<2) return false;for(int i2;i<x/i;i)if(x%i0)return false;return true; }int main() {int n; cin>>n;while(n--){int x; cin>>x;if(is_zs(x)) cout<<&quo…...
稀碎从零算法笔记Day31-LeetCode:接雨水
半月一去,望舒一轮,明天开始攻坚哈德题了 前言:非常经典的一道笔试题,看了保证血赚(今天银泰星笔试第四题就是这个) 题型:dp、模拟、双指针…… 链接:42. 接雨水 - 力扣ÿ…...
微前端的使用和注意事项 - qiankun
一、为什么使用微前端 微前端架构旨在解决单体应用在一个相对长的时间跨度下,由于参与的人员、团队的增多、变迁,从一个普通应用演变成一个巨石应用(Frontend Monolith)后,随之而来的应用不可维护的问题。微前端的核心目标是将巨石应用拆解成…...
uniapp微信小程序消息订阅详解
一、微信公众平台申请订阅模板 注意:订阅信息 这个事件 是 当用户 点击的时候触发 或者 是 支付成功后触发, 用户勾选 “总是保持以上选择,不再询问” 之后或长期订阅,下次订阅调用 wx.requestSubscribeMessage 不会弹窗…...
git 查看文件夹结构树
在Git中,没有直接的命令可以像文件系统那样展示一个可视化的文件结构树。但是,你可以使用一些外部工具或命令来达到这个目的。 以下是一些方法,你可以使用它们来查看Git仓库的文件结构树: 使用tree命令(如果你的系统已…...
设计模式一详解
一、观察者模式 当一个对象状态发生改变时,依赖它的对象全部会收到通知,并自动更新 场景:一个事件发生后,要执行一连串更新操作。传统的编程方式,就是在事件的代码之后直接加入处理逻辑。当更新的逻辑增多之后&#x…...
LuckyLilliaBot QQ群管理自动化实战指南:从零搭建高效智能管理方案
LuckyLilliaBot QQ群管理自动化实战指南:从零搭建高效智能管理方案 【免费下载链接】LuckyLilliaBot NTQQ的OneBot API插件 项目地址: https://gitcode.com/gh_mirrors/li/LuckyLilliaBot LuckyLilliaBot是一款基于NTQQ客户端与OneBot11协议的QQ机器人开发框…...
OpenClaw多模态扩展:Qwen3.5-4B-Claude处理截图与PDF
OpenClaw多模态扩展:Qwen3.5-4B-Claude处理截图与PDF 1. 为什么需要多模态能力? 去年夏天,我遇到一个头疼的问题:需要从几百份PDF报告里提取关键数据。手动复制粘贴不仅耗时,还容易出错。当时我就在想,如…...
RTX4090D显存优化:OpenClaw+Qwen3-32B-Chat批量处理千页PDF
RTX4090D显存优化:OpenClawQwen3-32B-Chat批量处理千页PDF 1. 为什么需要显存优化 当我第一次尝试用OpenClaw对接Qwen3-32B-Chat处理PDF文档时,遇到了一个棘手的问题——显存爆炸。当时只是处理一个200页的PDF,显存占用就飙到了22GB&#x…...
Flink技术实践-超时异常踩坑与优化
一、背景介绍在Flink实时计算的生产环境中,最令人头疼的往往不是复杂的业务逻辑,而是那些突如其来的“超时异常”。这些异常就像是系统中的“幽灵”,通常在业务高峰期或网络抖动时出现,导致作业重启、数据延迟甚至数据丢失。最近几…...
智能部署copaw:借助快马ai生成能理解自然语言的下载助手
最近在折腾一个叫copaw的工具时,发现手动下载部署特别麻烦,尤其是遇到网络波动和依赖冲突的时候。于是尝试用AI辅助开发的方式,通过自然语言描述需求,让InsCode(快马)平台的AI模型帮我生成一个智能化的下载部署助手。整个过程意外…...
降重不靠删,降AI不靠装——百考通用语义重构守住你的原创观点
在2026年的高校毕业季,一种新型的不公正在悄然制度化: 不是抄袭者被放过,而是原创者被怀疑; 不是敷衍者被批评,而是严谨者被标记; 不是懒惰者被警告,而是认真写了一篇好论文的人,被迫…...
HunyuanVideo-Foley实战案例:为纪录片自动匹配环境音效的完整工作流
HunyuanVideo-Foley实战案例:为纪录片自动匹配环境音效的完整工作流 1. 项目背景与需求 在纪录片制作过程中,环境音效的采集和匹配往往需要耗费大量时间和人力成本。传统方式需要音效师实地录制或从音效库中手动挑选,整个过程耗时且难以保证…...
Llama-3.2V-11B-cot从零部署:Docker镜像运行与端口映射详解
Llama-3.2V-11B-cot从零部署:Docker镜像运行与端口映射详解 1. 项目概述 Llama-3.2V-11B-cot是基于Meta Llama-3.2V-11B-cot多模态大模型开发的高性能视觉推理工具。它针对双卡4090环境进行了深度优化,特别适合想要体验Llama多模态大模型但缺乏专业部署…...
你还在给每个图片父元素加类名?CSS :has() 让选择器“逆天改命”
你还在给每个图片父元素加类名?CSS :has() 让选择器“逆天改命” 引言 “组长,这个需求我写不了。” “什么需求?” “产品经理说,所有包含图片的卡片,要在卡片上加一个‘带图标识’的边框。但是这些卡片是动态渲染的&…...
Dify知识库创建全攻略:从零开始搭建你的AI问答系统(附分段模式详解)
Dify知识库创建全攻略:从零开始搭建你的AI问答系统(附分段模式详解) 在AI技术快速渗透各行各业的今天,构建专属知识库已成为企业智能化转型的核心基础设施。Dify作为一款开箱即用的AI应用开发平台,其知识库功能尤其适合…...
