当前位置: 首页 > 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…...

利用ngx_stream_return_module构建简易 TCP/UDP 响应网关

一、模块概述 ngx_stream_return_module 提供了一个极简的指令&#xff1a; return <value>;在收到客户端连接后&#xff0c;立即将 <value> 写回并关闭连接。<value> 支持内嵌文本和内置变量&#xff08;如 $time_iso8601、$remote_addr 等&#xff09;&a…...

【OSG学习笔记】Day 18: 碰撞检测与物理交互

物理引擎&#xff08;Physics Engine&#xff09; 物理引擎 是一种通过计算机模拟物理规律&#xff08;如力学、碰撞、重力、流体动力学等&#xff09;的软件工具或库。 它的核心目标是在虚拟环境中逼真地模拟物体的运动和交互&#xff0c;广泛应用于 游戏开发、动画制作、虚…...

阿里云ACP云计算备考笔记 (5)——弹性伸缩

目录 第一章 概述 第二章 弹性伸缩简介 1、弹性伸缩 2、垂直伸缩 3、优势 4、应用场景 ① 无规律的业务量波动 ② 有规律的业务量波动 ③ 无明显业务量波动 ④ 混合型业务 ⑤ 消息通知 ⑥ 生命周期挂钩 ⑦ 自定义方式 ⑧ 滚的升级 5、使用限制 第三章 主要定义 …...

以下是对华为 HarmonyOS NETX 5属性动画(ArkTS)文档的结构化整理,通过层级标题、表格和代码块提升可读性:

一、属性动画概述NETX 作用&#xff1a;实现组件通用属性的渐变过渡效果&#xff0c;提升用户体验。支持属性&#xff1a;width、height、backgroundColor、opacity、scale、rotate、translate等。注意事项&#xff1a; 布局类属性&#xff08;如宽高&#xff09;变化时&#…...

Day131 | 灵神 | 回溯算法 | 子集型 子集

Day131 | 灵神 | 回溯算法 | 子集型 子集 78.子集 78. 子集 - 力扣&#xff08;LeetCode&#xff09; 思路&#xff1a; 笔者写过很多次这道题了&#xff0c;不想写题解了&#xff0c;大家看灵神讲解吧 回溯算法套路①子集型回溯【基础算法精讲 14】_哔哩哔哩_bilibili 完…...

C++ 基础特性深度解析

目录 引言 一、命名空间&#xff08;namespace&#xff09; C 中的命名空间​ 与 C 语言的对比​ 二、缺省参数​ C 中的缺省参数​ 与 C 语言的对比​ 三、引用&#xff08;reference&#xff09;​ C 中的引用​ 与 C 语言的对比​ 四、inline&#xff08;内联函数…...

2025盘古石杯决赛【手机取证】

前言 第三届盘古石杯国际电子数据取证大赛决赛 最后一题没有解出来&#xff0c;实在找不到&#xff0c;希望有大佬教一下我。 还有就会议时间&#xff0c;我感觉不是图片时间&#xff0c;因为在电脑看到是其他时间用老会议系统开的会。 手机取证 1、分析鸿蒙手机检材&#x…...

前端开发面试题总结-JavaScript篇(一)

文章目录 JavaScript高频问答一、作用域与闭包1.什么是闭包&#xff08;Closure&#xff09;&#xff1f;闭包有什么应用场景和潜在问题&#xff1f;2.解释 JavaScript 的作用域链&#xff08;Scope Chain&#xff09; 二、原型与继承3.原型链是什么&#xff1f;如何实现继承&a…...

图表类系列各种样式PPT模版分享

图标图表系列PPT模版&#xff0c;柱状图PPT模版&#xff0c;线状图PPT模版&#xff0c;折线图PPT模版&#xff0c;饼状图PPT模版&#xff0c;雷达图PPT模版&#xff0c;树状图PPT模版 图表类系列各种样式PPT模版分享&#xff1a;图表系列PPT模板https://pan.quark.cn/s/20d40aa…...

ip子接口配置及删除

配置永久生效的子接口&#xff0c;2个IP 都可以登录你这一台服务器。重启不失效。 永久的 [应用] vi /etc/sysconfig/network-scripts/ifcfg-eth0修改文件内内容 TYPE"Ethernet" BOOTPROTO"none" NAME"eth0" DEVICE"eth0" ONBOOT&q…...