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

【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对应的方法不能为空");}

实现思路:

  1. 声明自己的类注解,并要求被 Spring 收集
  2. 声明自己的方法注解,确保可以通过反射获取
  3. 借 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. 完整的代码后记 前言 需求&#xff1a; 用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&#xff08;Visual Studio&#xff09;是一款强大的开发工具&#xff0c;提供了许多常用快捷键&#xff0c;以提高开发效率。这些快捷键包括文件操作…...

ChatGPT指引:借助ChatGPT撰写学术论文的技巧

ChatGPT无限次数:点击直达 ChatGPT指引&#xff1a;借助ChatGPT撰写学术论文的技巧 在当今信息技术高度发达的时代&#xff0c;人工智能技术的不断发展为学术研究者提供了更多的便利和可能。其中&#xff0c;自然语言处理技术中的ChatGPT无疑是一种强大的工具&#xff0c;它能…...

魔改一个过游戏保护的CE

csdn审核不通过 网易云课堂有配套的免费视频 int0x3 - 主页 文章都传到github了 Notes/外挂/魔改CE at master MrXiao7/Notes GitHub 为什么要编译自己的CE 在游戏逆向的过程中&#xff0c;很多游戏有保护&#xff0c;我们运行原版CE的时候会被检测到 比如我们开着CE运…...

rust嵌入式开发之await

嵌入式经常有类似通过串口发送指令然后等待响应再做出进一步反应的需求。比如&#xff0c;通过串口以AT命令来操作蓝牙模块执行扫描、连接&#xff0c;需要根据实际情况进行操作&#xff0c;复杂的可能需要执行7、8条指令才能完成连接。 对于这样的需求&#xff0c;如果用异步…...

UE4_碰撞_碰撞蓝图节点——Line Trace For Objects(对象的线条检测)

一、Line Trace For Objects&#xff08;对象的线条检测&#xff09;&#xff1a;沿给定线条执行碰撞检测并返回遭遇的首个命中&#xff0c;这只会找到由Object types指定类型的对象。注意他与Line Trace By Channel(由通道检测线条&#xff09;的区别&#xff0c;一个通过Obje…...

抽象类和接口的简单认识

目录 一、抽象类 1.什么是抽象类 2.抽象类的注意事项 3.抽象类与普通类的对比 二、接口 1.接口的简单使用 2.接口的特性 3.接口的使用案例 4.接口和抽象类的异同 一、抽象类 所谓抽象类&#xff0c;就是更加抽象的类&#xff0c;也就是说&#xff0c;这个类不能具体描…...

python-pytorch获取FashionMNIST实际图片标签数据集

在查看pytorch官方文档的时候&#xff0c;在这里链接中https://pytorch.org/tutorials/beginner/basics/data_tutorial.html的Creating a Custom Dataset for your files章节&#xff0c;有提到要自定义数据集&#xff0c;需要用到实际的图片和标签。 在网上找了半天没找到&a…...

深入探秘Python生成器:揭开神秘的面纱

一、问题起源&#xff1a; 想象一下&#xff0c;您掌握了一种魔法&#xff0c;在代码世界里&#xff0c;您可以轻松呼唤出一个整数。然而&#xff0c;事情并不总是看起来那样简单。在Python的奇妙王国中&#xff0c;我遇到了一个有趣的谜题&#xff1a; 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“表演的舞台”&#xff0c;组件中所用到的所有数据、方法、监视数据、生命周期钩子等都需要配置在setup中。 2、setup的两种返回值&…...

若依框架学习使用

若依官网项目拉取下来介绍 | RuoYi 项目运行&#xff1a; 1.idea安装&#xff0c;可以运行前后端 编辑器idea、jdk环境安装、数据库mysql、navicat工具、redis(redis-server启动)安装 2.navicat数据库连接, 创建数据库ry-vue并导入数据脚本ry_2021xxxx.sql&#xff0c;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:接雨水

半月一去&#xff0c;望舒一轮&#xff0c;明天开始攻坚哈德题了 前言&#xff1a;非常经典的一道笔试题&#xff0c;看了保证血赚&#xff08;今天银泰星笔试第四题就是这个&#xff09; 题型&#xff1a;dp、模拟、双指针…… 链接&#xff1a;42. 接雨水 - 力扣&#xff…...

微前端的使用和注意事项 - qiankun

一、为什么使用微前端 微前端架构旨在解决单体应用在一个相对长的时间跨度下&#xff0c;由于参与的人员、团队的增多、变迁&#xff0c;从一个普通应用演变成一个巨石应用(Frontend Monolith)后&#xff0c;随之而来的应用不可维护的问题。微前端的核心目标是将巨石应用拆解成…...

uniapp微信小程序消息订阅详解

一、微信公众平台申请订阅模板 注意&#xff1a;订阅信息 这个事件 是 当用户 点击的时候触发 或者 是 支付成功后触发&#xff0c; 用户勾选 “总是保持以上选择&#xff0c;不再询问” 之后或长期订阅&#xff0c;下次订阅调用 wx.requestSubscribeMessage 不会弹窗&#xf…...

git 查看文件夹结构树

在Git中&#xff0c;没有直接的命令可以像文件系统那样展示一个可视化的文件结构树。但是&#xff0c;你可以使用一些外部工具或命令来达到这个目的。 以下是一些方法&#xff0c;你可以使用它们来查看Git仓库的文件结构树&#xff1a; 使用tree命令&#xff08;如果你的系统已…...

设计模式一详解

一、观察者模式 当一个对象状态发生改变时&#xff0c;依赖它的对象全部会收到通知&#xff0c;并自动更新 场景&#xff1a;一个事件发生后&#xff0c;要执行一连串更新操作。传统的编程方式&#xff0c;就是在事件的代码之后直接加入处理逻辑。当更新的逻辑增多之后&#x…...

【统计推断实战】从置信区间到假设检验:如何用数据做出可靠决策

1. 从产品迭代案例看统计推断的价值 最近团队上线了一个新功能&#xff0c;产品经理信心满满地宣称能提升15%的用户留存率。但上线一周后数据波动很大&#xff0c;有人觉得效果明显&#xff0c;有人却说毫无变化。这时候该信谁的&#xff1f;其实这就是统计推断大显身手的时刻—…...

Python内置模块:io、file、json、csv

一、io StringIO - 文本字符串的缓冲区 from io import StringIO# 创建StringIO对象 sio StringIO() # 空缓冲区 sio StringIO("initial text") # 带初始数据# 常用方法 sio.write("Hello ") # 写入字符串&…...

AI 驱动单元测试生成:智能优先级与自动化验证实践

1. 项目概述如果你和我一样&#xff0c;长期在维护一个中大型的 TypeScript 项目&#xff0c;那么“补单元测试”这件事&#xff0c;大概率是你技术债清单上那个永远在滚动、却很少被真正划掉的任务。手动写测试枯燥耗时&#xff0c;尤其是面对那些遗留的、逻辑复杂的业务函数时…...

5 款实用漏洞扫描工具,网安从业者必备收藏

漏洞扫描是指基于漏洞数据库&#xff0c;通过扫描等手段对指定的远程或者本地计算机系统的安全脆弱性进行检测&#xff0c;发现可利用漏洞的一种安全检测的行为。 在漏洞扫描过程中&#xff0c;我们经常会借助一些漏扫工具&#xff0c;市面上漏扫工具众多&#xff0c;其中有一…...

OpenClaw Memory启动器:快速构建AI记忆系统的开源脚手架

1. 项目概述&#xff1a;一个为AI记忆系统设计的开源启动器最近在折腾AI应用开发&#xff0c;特别是那些需要长期记忆和上下文管理的项目时&#xff0c;发现了一个挺有意思的GitHub仓库&#xff1a;christiancaviedes/openclaw-memory-starter。这本质上是一个为“OpenClaw Mem…...

Docker Compose 镜像检测脚本(支持自动扫描 + 手动输入 YAML)

在日常运维中&#xff0c;经常会遇到这样一个问题&#xff1a; docker-compose 文件里定义了很多镜像&#xff0c;但本地是否已经存在不清楚 如果一个个 docker pull 或 docker images 去对比&#xff0c;会非常低效。 因此我们可以写一个脚本&#xff0c;自动解析 docker-com…...

OpenClaw狂欢暗藏安全隐患,深圳机密计算科技端云一体方案筑牢AI Agent安全基座

AI Agent时代&#xff0c;安全信任的崩塌2026年初&#xff0c;OpenClaw横空出世&#xff0c;仅用60天打破React保持十年的GitHub Star纪录&#xff0c;成为当年热度最高的现象级开源项目。2026年3月&#xff0c;在英伟达GTC全球开发者大会上&#xff0c;黄仁勋直言称“OpenClaw…...

Python 爬虫反爬突破:CDN 防护节点穿透采集

前言 当下大型互联网站点、电商平台资讯门户、行业数据网站均全面接入 CDN 内容分发网络&#xff0c;借助全球节点缓存、流量调度、智能分流、节点 IP 隐身、区域访问限制等机制构建底层防护体系。传统爬虫直接请求源站 IP 的方式会被 CDN 节点拦截、跳转、限速、IP 封禁、节点…...

Windows系统级课堂管理软件反控制技术实现:JiYuTrainer内核驱动与API拦截架构解析

Windows系统级课堂管理软件反控制技术实现&#xff1a;JiYuTrainer内核驱动与API拦截架构解析 【免费下载链接】JiYuTrainer 极域电子教室防控制软件, StudenMain.exe 破解 项目地址: https://gitcode.com/gh_mirrors/ji/JiYuTrainer 在现代化教育信息化环境中&#xff…...

Midjourney咖啡印相为何总偏灰?揭秘RGB→Lab→咖啡染料光谱响应的3层色彩断层及校正算法

更多请点击&#xff1a; https://intelliparadigm.com 第一章&#xff1a;Midjourney咖啡印相为何总偏灰&#xff1f;揭秘RGB→Lab→咖啡染料光谱响应的3层色彩断层及校正算法 咖啡印相&#xff08;Coffee Cyanotype&#xff09;作为一种新兴的生物友好型物理输出工艺&#xf…...