自定义BeanPostProcessor实现自动注入标注了特定注解的Bean

  • 定义注解
@Target({ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface MyAnno {
}
  • 定义一个配置类
@Configuration
public class RestConfig {@MyAnno@Beanpublic PayDTO payDTO(){PayDTO payDTO = new PayDTO();payDTO.setPayNo("1");return payDTO;}@Beanpublic PayDTO payDTO1(){PayDTO payDTO = new PayDTO();payDTO.setPayNo("2");return payDTO;}}

这个配置类返回了两个PayDTO 类型的对象。

  • 定义使用类
@Component
public class MyConfigTest implements InitializingBean {@MyAnno@Autowired(required = false)private List<PayDTO> payDTOList = Collections.emptyList();@Overridepublic void afterPropertiesSet() throws Exception {System.out.println("payDTO = " + payDTOList);}
}

这里想只从容器中获取标注了@MyAnno注解的PayDTO对象,也就是说应该是只能获取到一个。

  • 定义BeanPostProcessor
@Component
public class MyAnnoPostProcesser implements BeanPostProcessor {@Autowiredprivate ApplicationContext applicationContext;@Overridepublic Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {//这里只考虑对@Autowired作用于属性上Field[] declaredFields = bean.getClass().getDeclaredFields();if (bean instanceof MyConfigTest){System.out.println("MyConfigTest");}for (Field field : declaredFields) {//判断当前属性是否标记了@MyAnno注解MyAnno annotation = field.getAnnotation(MyAnno.class);Autowired autowired = field.getAnnotation(Autowired.class);if (annotation != null && autowired != null) {field.setAccessible(true);//获取字段的类型Type genericType = field.getGenericType();if (genericType instanceof ParameterizedType) {//判断属性类型是否是一个参数化类型,例如 List<String> 这里的String就是泛型参数ParameterizedType parameterizedType = (ParameterizedType) genericType;Type rawType = parameterizedType.getRawType();//泛型原生类型是List类型if (rawType == List.class) {//获取参数化类型列表,每一个参数化列表可能又是一个泛型类型Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();Type argument = actualTypeArguments[0];if (argument instanceof Class) {Class<?> clazz = (Class<?>) argument;//从容器中获取对应此参数化类型并且标注了MyAnno注解的BeanMap<String, Object> beansWithAnnotation = applicationContext.getBeansWithAnnotation(MyAnno.class);if (beansWithAnnotation.size() > 0) {List<Object> beanList = beansWithAnnotation.entrySet().stream().filter(entry -> {Object value = entry.getValue();return value.getClass() == clazz;}).map(item -> item.getValue()).collect(Collectors.toList());//进行属性赋值try {field.set(bean, beanList);} catch (IllegalAccessException e) {throw new RuntimeException(e);}}}}}}}return bean;}
}

BeanPostProcessor实现原理:

  1. 获取Bean示例,并拿到这个Bean对象中声明的属性。

  2. 判断属性是否同时标注了MyAnno和Autowired注解。

  3. 获取属性的类型
    属性的类型返回值有多种情况,可能是Class、ParameterizedType、GenericType等
    如果是一个具体的类型则返回Class,如果是一个泛型类型,例如List,则返回ParameterizedType参数化类型,参数化类型的意思就是使用了泛型类型,并指定了泛型参数,这里的泛型参数就是PayDTO。

  4. parameterizedType.getRawType(); 获取泛型类型的原生类型,也就是List.class

  5. Type[] actualTypeArguments = parameterizedType.getActualTypeArguments(); 获取泛型类型的参数类型,例如List类的声明是
    List 这里的T就是泛型参数,而parameterizedType.getActualTypeArguments();返回的是一个数组,因为可能不止一个泛型类型,例如Map<K,V> 。

  6. 获取参数化类型的第一个元素,其实这里返回的就是PayDTO.class对象。

  7. 从容器中获取所有标注了MyAnno注解的Bean对象,并且遍历出是PayDTO类型的。

  8. 通过field.set(bean, beanList);实现属性值注入。

  9. 完成基于BeanPostProcessor实现的自定义注解Bean对象注入。

  • 踩坑

MyConfigTest对象标注的@Component,如果是标注@Configuration注解,此时Spring会生成一个代理对象,通过代理对象拿不到原始对象的相关属性了。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/893175.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

PyTorch使用教程- Tensor包

### PyTorch使用教程- Tensor包 PyTorch是一个流行的深度学习框架&#xff0c;它提供了一个易于使用的API来创建和操作张量&#xff08;Tensors&#xff09;。张量是一个多维数组&#xff0c;类似于NumPy中的ndarray&#xff0c;但它是基于GPU的&#xff0c;支持自动求导。本文…

国产编辑器EverEdit - 合并行

1 合并行 1.1 应用场景 在编写代码或其他场景下&#xff0c;有时需要把多行的内容缩减成一行&#xff0c;或者纯粹减少行数进行合并&#xff0c;比如&#xff1a;下面的字典的定义&#xff0c;每个元素占了一行&#xff0c;有点浪费&#xff0c;现在需要把它们缩减行数。 typ…

3 前端(中):JavaScript

文章目录 前言&#xff1a;JavaScript简介一、ECMAscript&#xff08;JavaScript基本语法&#xff09;1 JavaScript与html结合方式&#xff08;快速入门&#xff09;2 基本知识&#xff08;1&#xff09;JavaScript注释&#xff08;和Java注释一样&#xff09;&#xff08;2&am…

为AI聊天工具添加一个知识系统 之48 蒙板程序设计(第二版):Respect九宫格【社会形态:治理】

本文要点 1、词汇表Vocabulary &#xff08;普通名词&#xff09; 1) 三组词&#xff08;数据库支持的三个数字散列&#xff09;&#xff1a; 工作&#xff0c;工件&#xff0c;工具。论题&#xff0c;主题词&#xff0c;关键字。口号&#xff0c;符号&#xff0c;编号。 2…

RIME-CNN-LSTM-Attention多变量多步时序预测Matlab实现

SCI一区级 | Matlab实现RIME-CNN-LSTM-Multihead-Attention多变量多步时序预测 目录 SCI一区级 | Matlab实现RIME-CNN-LSTM-Multihead-Attention多变量多步时序预测预测效果基本介绍程序设计参考资料 预测效果 基本介绍 1.Matlab实现RIME-CNN-LSTM-Multihead-Attention霜冰算法…

一文读懂服务器的HBA卡

什么是 HBA 卡 HBA 卡&#xff0c;全称主机总线适配器&#xff08;Host Bus Adapter&#xff09; &#xff0c;是服务器与存储装置间的关键纽带&#xff0c;承担着输入 / 输出&#xff08;I/O&#xff09;处理及物理连接的重任。作为一种电路板或集成电路适配器&#xff0c;HBA…

mfc操作json示例

首先下载cJSON,加入项目; 构建工程,如果出现, fatal error C1010: unexpected end of file while looking for precompiled head 在cJSON.c文件的头部加入#include "stdafx.h"; 看情况,可能是加到.h或者是.cpp文件的头部,它如果有包含头文件, #include &…

综述:大语言模型在机器人导航中的最新进展!

简介 机器人导航是指机器人能够在环境中自主移动和定位的能力。本文系统地回顾了基于大语言模型&#xff08;LLMs&#xff09;的机器人导航研究&#xff0c;将其分为感知、规划、控制、交互和协调等方面。具体来说&#xff0c;机器人导航通常被视为一个几何映射和规划问题&…

owasp SQL 注入-03 (原理)

1: 先看一下注入界面: 点submit 后&#xff0c;可以看到有语法报错&#xff0c;说明已经起作用了: 报如下的错误: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near at line 1 2:…

Vscode:问题解决办法 及 Tips 总结

Visual Studio Code&#xff08;简称VSCode&#xff09;是一个功能强大的开源代码编辑器&#xff0c;广泛用于各种编程语言和开发场景&#xff0c;本博客主要记录在使用 VSCode 进行verilog开发时遇到的问题及解决办法&#xff0c;使用过程中的技巧 文章目录 扩展安装失败调试配…

Linux(NFS服务)

赛题拓扑&#xff1a; 题目&#xff1a; NFS&#xff1a; 共享/webdata/目录。用于存储AppSrv主机的WEB数据。仅允许AppSrv主机访问该共享。 [rootstoragesrv ~]# yum install nfs-utils -y [rootstoragesrv ~]# mkdir /webdata [rootstoragesrv ~]# chmod -R ow /webdata …

c.p.api.config.MyAuthenticationProvider

文章目录 1、URL1、AdminController3、AuthenticationProvider 2025-01-15 14:21:31.017 WARN 1972 --- [nio-8087-exec-8] c.p.api.config.MyAuthenticationProvider : 管理员:13524972741 登录失败:密码错误解释: 时间戳: 2025-01-15 14:21:31.017 - 表示日志记录的时间…

接口传参 data格式和json格式区别是什么

接口传参 data格式和json格式区别是什么 以下是接口传参 data 格式和 JSON 格式的区别&#xff1a; 定义和范围 Data 格式&#xff1a; 是一个较为宽泛的概念&#xff0c;它可以指代接口传递参数时所使用的任何数据的组织形式。包括但不限于 JSON、XML、Form 数据、纯文本、二进…

C++ 模拟真人鼠标轨迹算法 - 防止游戏检测

一.简介 鼠标轨迹算法是一种模拟人类鼠标操作的程序&#xff0c;它能够模拟出自然而真实的鼠标移动路径。 鼠标轨迹算法的底层实现采用C/C语言&#xff0c;原因在于C/C提供了高性能的执行能力和直接访问操作系统底层资源的能力。 鼠标轨迹算法具有以下优势&#xff1a; 模拟…

【Android学习】Kotlin随笔

文章目录 一. 集合1. 安全获取集合元素2. mutableList3. list遍历4. List 通过解构一次性给多个元素赋值5. Set集合 一. 集合 1. 安全获取集合元素 List.getOrElse(index: Int, defaultValue: (Int) -> T): T 函数原型 : List.getOrNull(index: Int): T? 函数原型 : 2. …

设置 Git 默认推送不需要输入账号和密码【Ubuntu、SSH】

如何设置 Git 默认推送不需要输入账号和密码 在使用 Git 管理代码时&#xff0c;许多开发者会遇到每次推送&#xff08;push&#xff09;或拉取&#xff08;fetch&#xff09;代码时都需要输入 GitHub 或 GitLab 等远程仓库的账号和密码的情况。虽然设置了用户名和电子邮件信息…

【ArcGIS微课1000例】0140:总览(鹰眼)、放大镜、查看器的用法

文章目录 一、总览工具二、放大镜工具三、查看器工具ArcGIS中提供了三种局部查看的工具: 总览(鹰眼)、放大镜、查看器,如下图所示,本文讲述这三种工具的使用方法。 一、总览工具 为了便于效果查看与比对,本实验采用全球影像数据(位于配套实验数据包中的0140.rar中),加…

Vue3数据响应式原理

什么是数据响应式 当数据变化时&#xff0c;引用数据的函数&#xff08;副作用函数&#xff09;自动重新执行。 即数据触发了函数的响应&#xff0c;如&#xff1a;视图渲染中使用了某数据&#xff0c;数据改变后&#xff0c;视图跟着自动更新。 触发者&#xff1a;数据 响应者…

前端开发中的状态管理与网络请求封装

本文将对比 Vuex 和 Pinia 在状态管理中的使用&#xff0c;并介绍如何封装 Axios 进行网络请求。此外&#xff0c;我们还将讨论动态路由、404 页面跳转以及面包屑导航的实现。 话不多说&#xff0c;正文开始~~~ 一、状态管理&#xff1a;Vuex 与 Pinia 对比 1. Vuex Vuex 是…

【AI】【RAG】使用WebUI部署RAG:数据优化与设置技巧详解

RAG(Retrieval-Augmented Generation)是一种通过知识库构建的高效问答系统。然而,在使用WebUI部署和优化RAG时,数据源管理和参数设置直接决定了系统的回答质量。本文将结合具体问题和优化方法,为您详细解读如何最大化RAG的性能和准确性。 数据源相关问题及解决方案 在实际…