spring扫描自定义注解注册bean
前言
我们知道,在spring中,我们只需要加上注解@Component
,就可以自动注入到spring容器中,如果我们自定义注解,怎么让spring识别到,注入到容器中呢,下面我们来看看。
基础使用
自定义注解
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface CustomizeComponent {
}
开启自定义注解的注解
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Import(CustomizeRegistrar.class) // 注意该注解,负责和spring建立关联
@Documented
public @interface EnableCustomizeComponent {String basePackages() default "";
}
自定义bean注册
public class CustomizeRegistrar implements ImportBeanDefinitionRegistrar {@SneakyThrows@Overridepublic void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {Map<String, Object> map = importingClassMetadata.getAnnotationAttributes(EnableCustomizeComponent.class.getName());// 获得要扫描的类String basePackages = (String) map.get("basePackages");if (!StringUtils.hasLength(basePackages)){ // basePackages为空的时候获取注解所在类的包路径basePackages = ClassUtil.getPackage(Class.forName(importingClassMetadata.getClassName()));}// 创建scanner,该类负责扫描包,并注册beanClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(registry);// 添加我们的自定义注解,要注意这里是IncludeFilter,不是excludeFilter,别写错了scanner.addIncludeFilter(new AnnotationTypeFilter(CustomizeComponent.class));scanner.scan(basePackages);}
}
测试
@CustomizeComponent
public class Person {public String getInfo(){return "这是测试信息";}
}@Component
public class AppRunner implements ApplicationRunner {@Autowiredprivate Person person;@Overridepublic void run(ApplicationArguments args) throws Exception {System.out.println("===" + person.getInfo());}
}@SpringBootApplication
@EnableCustomizeComponent
public class App {public static void main(String[] args) {SpringApplication.run(App.class, args);}
}
进阶使用
在使用mybatis、openFeign的时候我们是定义了接口,然后不需要实现也会帮助我们注入到容器中,然后可以相正常的bean一样使用,接下来我们看看是怎么实现的
开启自定义注解
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Import(MyFeignRegistrar.class)
@Documented
public @interface EnableMyFeign {String basePackages() default "";
}
方法上的注解
我们只需要在接口的方法上添加该注解,就可以发起网络请求
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface CustomizeGet {String url();}
注册器
public class MyFeignRegistrar implements ImportBeanDefinitionRegistrar {@SneakyThrows@Overridepublic void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {Map<String, Object> map = importingClassMetadata.getAnnotationAttributes(EnableMyFeign.class.getName());String basePackages = (String) map.get("basePackages");if (!StringUtils.hasLength(basePackages)){basePackages = ClassUtil.getPackage(Class.forName(importingClassMetadata.getClassName()));}FeignScanner scanner = new FeignScanner(registry);// 这里我们换了一种方式,定义的接口要继承Feign,而不需要添加注解scanner.addIncludeFilter(new AssignableTypeFilter(Feign.class){@Overrideprotected boolean matchClassName(String className) {return false;}});scanner.scan(basePackages);}// 继承ClassPathBeanDefinitionScanner,自定义自己的扫描器static class FeignScanner extends ClassPathBeanDefinitionScanner {public FeignScanner(BeanDefinitionRegistry registry) {super(registry);}@Overrideprotected Set<BeanDefinitionHolder> doScan(String... basePackages) {Set<BeanDefinitionHolder> beanDefinitionHolders = super.doScan(basePackages);for (BeanDefinitionHolder beanDefinitionHolder : beanDefinitionHolders) {GenericBeanDefinition beanDefinition =(GenericBeanDefinition) beanDefinitionHolder.getBeanDefinition();String beanClassName = beanDefinition.getBeanClassName();beanDefinition.getConstructorArgumentValues().addGenericArgumentValue(beanClassName);// 拿到beanDefinition,修改里面的beanClass为FeignFactoryBeanbeanDefinition.setBeanClass(FeignFactoryBean.class);}return beanDefinitionHolders;}// 注意,扫描的时候里面有个条件会判断对应的class是否非接口类型,这里要重写,我们的要求是接口类型,后边我们会通过FactoryBean创建动态代理@Overrideprotected boolean isCandidateComponent(AnnotatedBeanDefinition beanDefinition) {return beanDefinition.getMetadata().isInterface() && beanDefinition.getMetadata().isIndependent();}}
}// 空实现,担当一个标识的作用
public interface Feign {
}
工厂Bean
public class FeignFactoryBean<T extends Feign> implements FactoryBean<T> {private final Class<T> interfaceClass;public FeignFactoryBean(Class<T> interfaceClass) {this.interfaceClass = interfaceClass;}@Overridepublic T getObject() throws Exception {// 使用动态代理来创建Beanreturn (T) Proxy.newProxyInstance(interfaceClass.getClassLoader(), new Class[]{interfaceClass}, new Handler());}@Overridepublic Class<?> getObjectType() {return interfaceClass;}static class Handler<T> implements InvocationHandler {private final RestTemplate restTemplate = new RestTemplate();@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {if (method.getDeclaringClass().equals(Object.class)) {return method.invoke(this, args);}// 方法上有CustomizeGet注解的发起网络请求CustomizeGet customizeGet = method.getAnnotation(CustomizeGet.class);if (customizeGet != null) {return restTemplate.getForObject(customizeGet.url(), String.class);}return null;}}
}
测试
public interface Request extends Feign {@CustomizeGet(url = "https://www.baidu.com")String requestBaiDu();}@Component
public class AppRunner implements ApplicationRunner {@Autowiredprivate Request request;@Overridepublic void run(ApplicationArguments args) throws Exception {String str = request.requestBaiDu();System.out.println(str);}
}@SpringBootApplication
@EnableMyFeign
public class App {public static void main(String[] args) {SpringApplication.run(App.class, args);}
}
相关文章:
spring扫描自定义注解注册bean
前言 我们知道,在spring中,我们只需要加上注解Component,就可以自动注入到spring容器中,如果我们自定义注解,怎么让spring识别到,注入到容器中呢,下面我们来看看。 基础使用 自定义注解 Tar…...
【RL系列】StepFun之Open-Reasoner-Zero
1. 简介 开源了一个大规模RL训练框架之Open-Reasoner-Zero,仅使用vanilla PPO,GAE中参数 λ 1 , γ 1 \lambda 1, \gamma 1 λ1,γ1,rule-based reward,不需要KL regularization就可以增加response length和benchmark上的指标。…...
括号匹配问题--栈
括号匹配问题 栈的应用代码概览栈操作函数详解1.初始化栈(stackInit)2.向栈中压入元素(stackpush)3.获取栈顶元素(stacktop)4.弹出栈顶元素(stackpop)5.销毁栈(stackdest…...
LangChain4j(7):Springboot集成LangChain4j实现知识库RAG
我们之前的直接整合进SpringBoot进行实战,最终其实还会将查询到的内容,和对话上下文组合起来,发给LLM为我们组织语言进行回答: 配置一个Content Retriever 内容检索器,提供向量数据库和向量模型及其他参数将内容检索器绑定到AiSe…...
企业使用Excel开展数据分析限制和建议完整版
Excel作为企业数据分析的常用工具,虽然功能强大,但也存在一些限制和使用时的注意事项。以下是综合整理的关键点: 一、Excel在企业数据分析中的限制 数据处理规模有限 Excel的行列限制(如Excel 2019及之前版本最多支持1,048,576行…...
41、web前端开发之Vue3保姆教程(五 实战案例)
一、项目简介和需求概述 1、项目目标 1.能够基于Vue3创建项目 2.能够基本Vue3相关的技术栈进行项目开发 3.能够使用Vue的第三方组件进行项目开发 4.能够理解前后端分离的开发模式 2、项目概述 使用Vue3结合ElementPlus,ECharts工具实现后台管理系统页面,包含登录功能,…...
Quill富文本编辑器支持自定义字体(包括新旧两个版本,支持Windings 2字体)
文章目录 1 新版(Quill2 以上版本)2 旧版(Quill1版本) 1 新版(Quill2 以上版本) <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8" /><meta n…...
Flutter命令行打包打不出ipa报错
Flutter打包ipa报错解决方案 在Flutter开发中,打包iOS应用时可能会遇到以下错误: error: exportArchive: The data couldn’t be read because it isn’ in the correct format. 或者 Encountered error while creating the IPA: error: exportArchive…...
UV安装与使用
1. 概述 GitHub:astral-sh/uv: An extremely fast Python package and project manager, written in Rust. 官网:uv An extremely fast Python package and project manager, written in Rust. 效率神器,基于Rust实现,比传统工具快…...
SQL练习题
数据表介绍 –1.学生表 Student(SId,Sname,Sage,Ssex) --SId 学生编号,Sname 学生姓名,Sage 出生年月,Ssex 学生性别–2.课程表 Course(CId,Cname,TId) --CId 课程编号,Cname 课程名称,TId 教师编号–3.教师表 Teacher(TId,Tname) --TId 教师编号,Tname 教师姓名–4.成绩表…...
Rust Command无法执行*拓展解决办法
async fn run_cmd_async_out<I, S>(cmd: &str, args: I, timeout_s: u64, with_http_proxy: bool) -> Result<String> whereI: IntoIterator<Item S>,S: AsRef<OsStr>, {let mut cmd tokio::process::Command::new(cmd);// 让 sh 来运行命令&…...
利用Hadoop MapReduce实现流量统计分析
在现代大数据时代,处理和分析海量数据是一项常见的任务。Hadoop MapReduce提供了一种高效的方式来处理分布式数据集。本文将通过一个具体的示例——流量统计分析,来展示如何使用Hadoop MapReduce进行数据处理。 项目背景 在电信行业中,对用…...
Spring Boot应用程序接入ELK-003
Spring Boot应用程序接入ELK 一、项目依赖集成 在将Spring Boot应用程序接入ELK日志搜索引擎时,首先要在项目中集成相关依赖: (一)Logstash依赖 <dependency><groupId>net.logstash.logback</groupId><a…...
spark(一)
本节课围绕Spark Core展开深入学习,了解了Spark的运行架构、核心组件、核心概念以及提交流程,明晰其整体运行机制与各部分协作逻辑。重点聚焦于两个核心组件;对RDD相关概念进行了细致学习,包括其核心属性、执行原理、序列化方式、…...
绿电直供零碳园区:如何用清洁能源重塑企业竞争力?
引言 在全球积极应对气候变化的大背景下,“双碳” 目标已成为世界各国实现可持续发展的关键战略方向。我国也明确提出要在 2030 年前实现碳达峰,2060 年前实现碳中和,这一宏伟目标的提出,对各行各业都产生了深远影响,…...
国家科技奖项目答辩ppt设计_科技进步奖PPT制作_技术发明奖ppt美化_自然科学奖ppt模板
国家科学技术奖 为了奖励在科学技术进步活动中做出突出贡献的公民、组织,调动科学技术工作者的积极性和创造性,加速科学技术事业的发展,提高综合国力而设立的一系列奖项。每两三年评选一次。 科技奖ppt案例 WordinPPT / 持续为双一流高校、…...
LLM应用实战2-理解Tokens
文章目录 基本定义Tokenization 的作用主流 Tokenization 算法示例示例GPT-4o&GPT-4o miniGPT-3.5 & GPT-4 基本定义 Tokens 是大型语言模型(LLM)处理文本或代码的最小语义单元,可包含以下形式: 字符(如英文…...
【Java面试系列】Spring Boot微服务架构下的分布式事务处理与性能优化详解 - 3-5年Java开发必备知识
【Java面试系列】Spring Boot微服务架构下的分布式事务处理与性能优化详解 - 3-5年Java开发必备知识 引言 在当今的微服务架构中,分布式事务处理和性能优化是面试中经常被问及的高频话题。随着系统规模的扩大,如何保证数据一致性和系统性能成为了开发者…...
NO.80十六届蓝桥杯备战|数据结构-字符串哈希|兔子与兔子(C++)
回忆:哈希函数与哈希冲突 哈希函数:将关键字映射成对应的地址的函数,记为 Hash(key) Addr 。哈希冲突:哈希函数可能会把两个或两个以上的不同关键字映射到同⼀地址,这种情况称为哈希冲突。 字符串哈希 定义⼀个把字…...
Spring MVC 请求类型注解详解
Spring MVC 请求类型注解详解 1. 核心注解分类 Spring MVC 中的请求处理注解分为以下几类: 类别注解示例作用范围方法级注解RequestMapping, GetMapping 等方法级别参数级注解RequestParam, RequestBody方法参数模型/会话注解ModelAttribute, SessionAttributes方…...
RabbitMQ的死信队列和ttl
TTL ttl即过期时间,rbbitmq可以对队列和消息设置过期时间,当消息到存活时间之后,还没有被消费,就会被自动清除 例如:在网上购物,经常会遇到一个场景,当下单超过24小时还未付款,订单…...
[特殊字符] Hyperlane:Rust 高性能 HTTP 服务器库,开启 Web 服务新纪元!
🚀 Hyperlane:Rust 高性能 HTTP 服务器库,开启 Web 服务新纪元! 🌟 什么是 Hyperlane? Hyperlane 是一个基于 Rust 语言开发的轻量级、高性能 HTTP 服务器库,专为简化网络服务开发而设计。它支…...
【后端开发】Spring MVC-常见使用、Cookie、Session
文章目录 代码总结初始化传递参数单参数多参数 传递对象后端参数重命名(后端参数映射)必传参数设置非必传参数 传递数组传递集合传递JSON数据JSON语法JSON格式转换JSON优点传递JSON对象 获取URL中参数传递文件 Cookie与SessionCookieCookie机制 SessionC…...
Element Plus 去掉表格外边框
使用el-table组件拖拽时, 想使用自定义样式进行拖拽, 想去掉外边框, 并在表头加入竖杠样式 css代码: <style lang"less" scoped>// 表格右边框线 .el-table--border::after {width: 0; }// 表格上边框线 :deep(.el-table__i…...
安全厂商安全理念分析
奇安信(toB企业安全) 安全理念:率先提出 “内生安全” 理念。即把安全能力内置到信息化环境中,通过信息化系统和安全系统的聚合、业务数据和安全数据的聚合、IT 人才和安全人才的聚合,让安全系统像人的免疫系统一样&a…...
GaussDB Plan Hint调优实战:从执行计划控制到性能优化
GaussDB Plan Hint调优实战:从执行计划控制到性能优化 一、GaussDB Plan Hint核心价值 执行计划控制原理 mermaid graph TD A[SQL提交] --> B(优化器决策) B --> C{使用Hint?} C -->|是| D[强制指定执行路径] C -->|否| E[自动生成最优计划] D --&g…...
【力扣hot100题】(078)跳跃游戏Ⅱ
好难啊,我愿称之为跳崖游戏。 依旧用了两种方法,一种是我一开始想到的,一种是看答案学会的。 我自己用的方法是动态规划,维护一个数组记录到该位置的最少步长,每遍历到一个位置就嵌套循环遍历这个位置能到达的位置&a…...
基于 DeepSeek API 实现一个简单的数据分析 Agent
写在前面 本文将带你一步步了解: 什么是(简单的)数据分析 Agent?为什么使用 LLM 进行数据分析?如何利用 DeepSeek API 的能力?设计并实现一个基于 Python 和 Pandas 的基础数据分析 Agent。探讨其局限性、安全考量及未来方向。我们的目标是构建一个简单的 Agent,它能理…...
VUE3+TS+elementplus+Django+MySQL实现从前端增加数据存入数据库,并显示在前端界面上
一、前言 前面实现了从数据库读取数据,显示在前端界面上VUE3TSelementplusDjangoMySQL实现从数据库读取数据,显示在前端界面上,以及使用VUE3TSelementplus创建一个增加按钮。今天通过在前端的增加功能,新增数据,传到后…...
Django 创建CSV文件
Django使用Python内置的CSV库来创建动态的CSV(逗号分隔值)文件。我们可以在项目的视图文件中使用这个库。 让我们来看一个例子,这里我们有一个Django项目,我们正在实现这个功能。创建一个视图函数 getfile() 。 Django CSV例子 …...
最新版RubyMine超详细图文安装教程,带补丁包(2025最新版保姆级教程)
目录 前言 一、RubyMine最新版下载 二、RubyMine安装 三、RubyMine补丁 四、运行RubyMine 前言 RubyMine是由JetBrains开发的集成开发环境(IDE),专为Ruby和Ruby on Rails开发者设计,提供智能代码补全、调试、测试、版本控制集…...
spring之JdbcTemplate、GoF之代理模式、面向切面编程AOP
一、JdbcTemplate JdbcTemplate是Spring提供的一个JDBC模板类,是对JDBC的封装,简化JDBC代码。 当然,你也可以不用,可以让Spring集成其它的ORM框架,例如:MyBatis、Hibernate等。 接下来我们简单来学习一下&…...
【QT】QT中的文件IO
QT中的文件IO 一、有关文件IO的类二、步骤1、定义QFile的对象,与要读写的文件绑定在一起2、打开文件3、读写文件1)读取文件2)写入文件 4、关闭文件5、示例代码: 三、QString和QByteArray之间的转换1、方法2、示例代码: 四、QFileI…...
linux安装mysql常出现的问题
wget http://repo.mysql.com/mysql-community-release-el7-5.noarch.rpm rpm -ivh mysql-community-release-el7-5.noarch.rpm yum update yum install mysql-server 权限设置: chown -R mysql:mysql /var/lib/mysql/ 初始化 MySQL: mysqld --initiali…...
ArcGIS Engine开发教程--从零搭建GIS桌面应用
目录 一、ArcGIS Engine简介 1.1 什么是ArcGIS Engine? 1.2 应用场景 二、环境搭建 2.1 安装准备 2.2 配置项目 三、核心对象与基础概念 3.1 核心组件 3.2 接口编程 四、实战:开发简易地图查看器 4.1 加载地图文档 4.2 添加矢量图层 4.3 实…...
DeepSeek 助力 Vue3 开发:打造丝滑的日历(Calendar)
前言:哈喽,大家好,今天给大家分享一篇文章!并提供具体代码帮助大家深入理解,彻底掌握!创作不易,如果能帮助到大家或者给大家一些灵感和启发,欢迎收藏关注哦 💕 目录 Deep…...
Conda使用方法详解
Conda是一个开源的包管理和环境管理系统,主要用于Python/R等科学计算领域,可以轻松管理不同项目的依赖关系。以下是Conda的详细使用方法: 一、安装与配置 1.安装Miniconda/Anaconda Miniconda是精简版,只包含conda和Python Ana…...
CausalML 基于机器学习算法的因果推理方法
CausalML 是一个 Python 包,它使用基于最新研究的机器学习算法提供一套提升建模和因果推理方法。它提供了一个标准界面,允许用户从实验或观察数据中估计条件平均处理效应 (CATE),也称为个体治疗效应 (ITE&a…...
HTML的svg元素
<svg>元素 <svg>是一种用于描述二维矢量图形的 XML 格式,可以直接嵌入 HTML 文档中。 <svg>基本用法 <svg>的几种基本用法,包括圆形,正方形,三角形,直线 ,折线等 <body><svg widt…...
文件上传、读取与包含漏洞解析及防御实战
一、漏洞概述 文件上传、读取和包含漏洞是Web安全中常见的高危风险点,攻击者可通过此类漏洞执行恶意代码、窃取敏感数据或直接控制服务器。其核心成因在于开发者未对用户输入内容进行充分验证或过滤,导致攻击者能够绕过安全机制,上传或执行…...
物联网与边缘计算之物联网架构(感知层、网络层、应用层)
一、感知层:数据采集与智能终端 1. 核心功能 感知层是物联网的数据入口,通过物理设备(如传感器、RFID标签)实时采集环境、设备或生物体的物理量(温度、湿度)、标识信息(如二维码)及…...
nvm使用手册
一、安装前准备 1. 卸载现有 Node.js(如已安装) # 删除全局 node 模块 sudo rm -rf /usr/local/lib/node_modules# 删除 node 可执行文件 sudo rm -rf /usr/local/bin/npm sudo rm -rf /usr/local/bin/node# 删除其他残留文件 sudo rm -rf ~/.npm sudo…...
Maven error:Could not transfer artifact
问题描述 当项目从私有仓库下载依赖时,Maven 报错,无法从远程仓库下载指定的依赖包,错误信息如下: Could not transfer artifact com.ding.abcd:zabk-java:pom from/to releases (http://192.1122.101/repory/mavenleases/): 此…...
【操作系统(Linux)】——通过案例学习父子进程的线程异步性
本篇旨在通过几个案例来学习父子进程的线程异步性 一、父进程与子进程 我们将要做的: 创建父子进程,观察父子进程执行的顺序,了解进程执行的异步行为 源代码: #include <stdio.h> #include <sys/types.h> #include…...
汽车CAN总线采样点和采样率详解
写在前面 本篇文章主要讲解在汽车电子中CAN总线采样率的相关知识点,内容涉及CAN波特率、采样点、时间份额、同步跳转宽度以及采样率的计算。 若有相关问题,欢迎评论沟通,共同进步。(*^▽^*) 1、CAN波特率 CAN波特率常规分为250kbps和500kbps,本文章主要以这两个波特率为…...
一款基于 .NET 8 + Vue 开源的、企业级中后台权限管理系统
前言 今天大姚给大家分享一款基于 .NET 8 Vue 开源、前后端分离的企业级中后台权限管理系统,助力快速完成常规业务需求开发:ApeVolo.Admin。 项目介绍 ApeVolo.Admin 一款基于.NET 8、SqlSugar、Vue、Elment UI、RBAC、前后端分离、开源(…...
创建两个进程
文章目录 创建两个进程**2. 实现思路及源代码**2.1 实现思路2.1.1 fork() 函数2.1.2 思路分析 2.2 源代码2.2.1 源代码分析2.2.2 源代码测试结果 **3. 打印进程树**3.1 tmux操作步骤3.1.1 启动 tmux3.1.2 分屏操作(Ctrlb是在告诉系统准备输入一个快捷键)…...
Zephyr、FreeRTOS、RT-Thread 定时器区别分析
一、核心特性对比 特性ZephyrFreeRTOSRT-Thread定时器类型系统定时器(k_timer)、硬件定时器软件定时器(基于系统tick)软件定时器、硬件定时器定时模式单次、周期性单次、自动重载(周期性)单次、周期、自定…...
.NET 中的深拷贝实现方法
在 .NET 中实现深拷贝(Deep Copy)有几种常用方法,深拷贝是指创建一个新对象,并递归地复制原对象及其所有引用对象,而不仅仅是复制引用。 目录 1. 使用序列化/反序列化2. 使用 JSON 序列化(Newtonsoft.Json…...
Vue/React组件/指令/Hooks封装的基本原则以及示例
一、组件封装原则与示例 Vue组件封装 核心原则 • 单一职责:每个组件只解决一个功能(如分页、过滤表单) • Props控制输入:通过定义明确的Props接口接收外部数据(类型校验、默认值) • Emit事件通信:子组件通过$emit向父组件传递动作(如分页切换) • 插槽扩展性:使用…...