简单的手动实现spring中的自动装配案例

news2025/2/24 18:57:56

简简单单的实现一个spring中的自动装配和容器管理的小骚操作。

1,创建AutoSetBean.java

使用injectBeans静态方法,可以扫描指定包下的所有带MyInject注解的字段,如果在beans的Map中存在这个字段的实例化类,则执行装配。

import java.lang.reflect.Field;
import java.util.Set;
import org.example.test.custominj.myAnno.MyInject;
import org.reflections.Reflections;
import org.reflections.scanners.Scanners;
import org.reflections.util.ConfigurationBuilder;

public class AutoSetBean {

    public static void injectBeans(String packageName) {
        // 使用Reflections库来扫描指定包名下的所有类
        Reflections reflections = new Reflections(new ConfigurationBuilder()
                .forPackages(packageName)
                .addScanners(Scanners.FieldsAnnotated)
        );

        // 获取所有带有@MyInject注解的字段
        Set<Field> fields = reflections.getFieldsAnnotatedWith(MyInject.class);

        for (Field field : fields) {
            try {
                // 获取字段所在的类
                Class<?> declaringClass = field.getDeclaringClass();
                // 设置字段可访问
                field.setAccessible(true);

                // 如果MyBean.beans中已经存在这个类的实例,则直接使用
                Object instance = MyBean.beans.get(declaringClass);
                if (instance == null) {
                    // 如果不存在这个类的实例,则创建一个新的实例
                    instance = declaringClass.getDeclaredConstructor().newInstance();
                    MyBean.beans.put(declaringClass, instance);
                }

                // 获取需要注入的字段的类型
                Class<?> fieldType = field.getType();

                // 从MyBean.beans中获取该类型的实例
                Object beanToInject = MyBean.beans.get(fieldType);

                if (beanToInject != null) {
                    // 注入实例
                    field.set(instance, beanToInject);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}

2, 创建MyBean.java

通过使用registerBean静态方法,扫描传入的包名,检查其是否有@MyRegister注解,并将所有有此注解的类实例化后装入beans中,以备后续的装配。


import org.example.test.custominj.myAnno.MyRegister;
import org.reflections.Reflections;
import org.reflections.scanners.Scanners;
import org.reflections.util.ConfigurationBuilder;

import java.util.HashMap;
import java.util.Map;
import java.util.Set;

public class MyBean {
    public static Map<Class<?>, Object> beans = new HashMap<>();

    public static void registBean(String packageName) {
        // 配置Reflections库
        Reflections reflections = new Reflections(new ConfigurationBuilder()
                .forPackages(packageName)
                .addScanners(Scanners.TypesAnnotated)
        );

        // 获取所有带有@MyRegister注解的类
        Set<Class<?>> annotatedClasses = reflections.getTypesAnnotatedWith(MyRegister.class);

        for (Class<?> clazz : annotatedClasses) {
            try {
                // 实例化对象并放入beans Map中
                beans.put(clazz, clazz.getDeclaredConstructor().newInstance());
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}

3, 创建MyInject.java 和MyRegister注解

配置两个自定义注解,用于标识是否执行装配。


import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface MyInject {
}

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

@Retention(RetentionPolicy.RUNTIME)
public @interface MyRegister {
}

4,创建测试的Client.java 和被注入的MyService.java

@MyRegister作用于类上,注释后可以将这个类放入beans中,

@MyInject作用于字段,可以实现从容器中找到特定类型的实例化对象后执行装配。

import org.example.test.custominj.myAnno.MyInject;
import org.example.test.custominj.myAnno.MyRegister;

@MyRegister
public class Client {
    @MyInject
    private MyService myService;

    public void doSomething() {
        myService.doSomething();
    }
}

import org.example.test.custominj.myAnno.MyRegister;


@MyRegister
public class MyService {
    public void doSomething() {
        System.out.println("do something");
    }
}

5,创建测试类

@Test 测试自定义的自动装配

    @Test
    public void test4() {
        MyBean.registBean("org.example.test.myinjtest");
        // 打印已注册的beans
        for (Map.Entry<Class<?>, Object> entry : MyBean.beans.entrySet()) {
            System.out.println(entry.getKey() + ": " + entry.getValue());
        }
        AutoSetBean.injectBeans("org.example.test.myinjtest");
        client = (Client) MyBean.beans.get(Client.class);
        client.doSomething();
    }

执行结果,成功执行Service下的dosomething方法,成功打印!

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

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

相关文章

c语言题目:成绩管理系统

&#x1f3c6;本文收录于「Bug调优」专栏&#xff0c;主要记录项目实战过程中的Bug之前因后果及提供真实有效的解决方案&#xff0c;希望能够助你一臂之力&#xff0c;帮你早日登顶实现财富自由&#x1f680;&#xff1b;同时&#xff0c;欢迎大家关注&&收藏&&…

Windows系统下载安装ngnix

一 nginx下载安装 nginx是HTTP服务器和反向代理服务器&#xff0c;功能非常丰富&#xff0c;在nginx官网首页&#xff0c;点击download 在download页面下&#xff0c;可以选择Stable version稳定版本&#xff0c;点击下载 将下载完成的zip解压即可&#xff0c;然乎在nginx所在…

【MySQL】事务四大特性以及实现原理

事务四大特性 原子性&#xff08;Atomicity&#xff09; 事务中的所有操作要么全部完成&#xff0c;要么全部不执行。如果事务中的任何一步失败&#xff0c;整个事务都会被回滚&#xff0c;以保持数据的完整性。 一致性&#xff08;Consistency&#xff09; 事务应确保数据库…

集智书童 | 英伟达和斯坦福基于 Transformer 的异常检测最新研究!

本文来源公众号“集智书童”&#xff0c;仅用于学术分享&#xff0c;侵权删&#xff0c;干货满满。 原文链接&#xff1a;英伟达和斯坦福基于 Transformer 的异常检测最新研究&#xff01; 在作者推动各种视觉任务性能边界的同时&#xff0c;模型的大小也在相应增长。为了跟上…

SPIN-Diffusion:自我博弈微调提升文本到图像扩散模型性能

扩散模型作为生成AI的关键实体&#xff0c;已经在多个领域展现出了卓越的能力。然而&#xff0c;现有的扩散模型&#xff0c;如Stable Diffusion和SDXL&#xff0c;通常在预训练阶段后需要进行微调以更好地符合人类偏好。最近&#xff0c;研究者们开始尝试使用强化学习&#xf…

昇思MindSpore学习笔记4-03生成式--Diffusion扩散模型

摘要&#xff1a; 记录昇思MindSpore AI框架使用DDPM模型给图像数据正向逐步添加噪声&#xff0c;反向逐步去除噪声的工作原理和实际使用方法、步骤。 一、概念 1. 扩散模型Diffusion Models DDPM(denoising diffusion probabilistic model) &#xff08;无&#xff09;条件…

06-6.4.4 拓扑排序

&#x1f44b; Hi, I’m Beast Cheng &#x1f440; I’m interested in photography, hiking, landscape… &#x1f331; I’m currently learning python, javascript, kotlin… &#x1f4eb; How to reach me --> 458290771qq.com 喜欢《数据结构》部分笔记的小伙伴可以…

计算机网络浅谈—什么是 OSI 模型?

开放系统通信&#xff08;OSI&#xff09;模型是一个代表网络通信工作方式的概念模型。 思维导图 什么是 OSI 模型&#xff1f; 开放系统互连 (OSI) 模型是由国际标准化组织创建的概念模型&#xff0c;支持各种通信系统使用标准协议进行通信。简单而言&#xff0c;OSI 为保证…

C++左值右值

在C中&#xff0c;左值&#xff08;lvalue&#xff09;和右值&#xff08;rvalue&#xff09;是表达式分类的关键概念&#xff0c;它们主要影响表达式的赋值、函数调用以及操作符的使用方式。这些概念在C11及以后的版本中变得更加重要&#xff0c;因为引入了移动语义和右值引用…

蓄势高飞逐“新”空,卓翼飞思助力打造低空经济产业领域人才智库

2024年&#xff0c;“低空经济”首次写入政府工作报告&#xff0c;掀开新兴产业的崭新一页&#xff0c;而后迅速在全国各地呈现如火如荼的发展态势。这片蕴藏着巨大潜力和产业的蓝海&#xff0c;正蓄势聚能、乘势而起&#xff0c;站在发展的新风口上&#xff0c;面对新前景和新…

MongoDB集群搭建-最简单

目录 前言 一、分片概念 二、搭建集群的步骤 总结 前言 MongoDB分片&#xff08;Sharding&#xff09;是一种水平扩展数据库的方法&#xff0c;它允许将数据分散存储在多个服务器上&#xff0c;从而提高数据库的存储容量和处理能力。分片是MongoDB为了应对大数据量和高吞吐量需…

ONLYOFFICE最新8.1版本——桌面编辑器简单测评

前言 大家好&#xff0c;我是小雨&#xff0c;看到最近ONLYOFFICE更新了最新的版本&#xff0c;更新了一下当前版本来具体的测评一下&#xff0c;先来看看官网提供的各类更新信息&#xff0c;下面是我找到的三个主页&#xff0c;包括功能演示链接&#xff0c;官网连接以及专门…

Ros2中goal_handle状态SUCCEED及ACCEPTED及CANCLED在rclpy中的死循环(彻底解决版本)

承接上文&#xff0c;遇到了在动作通信开发中&#xff0c;使用rclpy编写代码进行feedback等操作&#xff0c;但所有逻辑均编写完后&#xff0c;却无法将goal_handle提交为succeed状态&#xff0c;之前的解决方案是更改自己重写的execute()函数名为my_execute()并且在提交SUCCEE…

开始尝试从0写一个项目--后端(二)

实现学生管理 新增学生 接口设计 请求路径&#xff1a;/admin/student 请求方法&#xff1a;POST 请求参数&#xff1a;请求头&#xff1a;Headers&#xff1a;"Content-Type": "application/json" 请求体&#xff1a;Body&#xff1a; id 学生id …

N5 使用Gensim库训练Word2Vec模型

&#x1f368; 本文为&#x1f517;365天深度学习训练营 中的学习记录博客&#x1f356; 原作者&#xff1a;K同学啊# 前言 前言 这周学习训练一个Word2Vec模型&#xff0c;并进行一些基本的词向量操作。 Word2Vec 模型 Word2Vec 是一种基于神经网络的词向量表示方法&#x…

零基础STM32单片机编程入门(八)定时器PWM输入实战含源码视频

文章目录 一.概要二.PWM输入框架图三.CubeMX配置一个PWM输入例程1.硬件准备2.创建工程3.调试 四.CubeMX工程源代码下载五.讲解视频链接地址六.小结 一.概要 脉冲宽度调制(PWM)&#xff0c;是英文“Pulse Width Modulation”的缩写&#xff0c;简称脉宽调制&#xff0c;是利用单…

数学建模算法目标规划

在人们的生产实践中&#xff0c;经常会遇到如何利用现有资源来安排生产&#xff0c;以取得最大经济 效益的问题。此类问题构成了运筹学的一个重要分支—数学规划&#xff0c;而线性规划(Linear Programming 简记 LP)则是数学规划的一个重要分支。特别是在计算机能处理成千上万个…

在电子表格中对多列数据去重

一、数据展示 二、代码 Sub 选中区域数据去重()Dim arr()Dim c, d, id Selection.Counti 0For Each c In SelectionIf c.Value <> "" ThenReDim Preserve arr(0 To i)arr(i) c.Valuei i 1End IfNextarr 一维去重(arr)i 0For Each c In Range("O2&…

35.哀家要长脑子了!--二分

模板 int check() {...} // 检查这个数是否符合相应的要求// 把区间[l, r] 划分成[l, mid] 和 [mid1, r] 时使用 // 找到数组中第一个大于等于某一值得元素或满足特定条件的第一个位置 int bsearch_1(int l, int r){int mid l r >> 1;while(l < r) {if(check(mi…

C++(Qt)-GIS开发-简易瓦片地图下载器

Qt-GIS开发-简易瓦片地图下载器 文章目录 Qt-GIS开发-简易瓦片地图下载器1、概述2、安装openssl3、实现效果4、主要代码4.1 算法函数4.2 瓦片地图下载url拼接4.3 多线程下载 5、源码地址6、参考 更多精彩内容&#x1f449;个人内容分类汇总 &#x1f448;&#x1f449;GIS开发 …