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

仿写简单IOC

目录

TestController类:

UserService类:

 核心代码SpringIOC:

Autowired和Component注解

SpringIOCTest 类 

​编辑

总结:


TestController类:

@Component
public class TestController {@Autowiredprivate UserService userService;public void test(){userService.addUser("我口袋只剩玫瑰一片","此行又山高路远");}
}

UserService类:

@Component
public class UserService {public void addUser(String a,String b){System.out.println(a);System.out.println(b);}
}

 核心代码SpringIOC:

public class SpringIOC {private List<String> beanNames;private List<String> filePaths;private String basePath;private String basePackage;private Map<String, Object> beans =new HashMap<>();/*** 扫描所有的文件信息信息,存到了 filePaths*/private void scan() throws FileNotFoundException {File file = new File(basePath);filePaths = new ArrayList<>();if(file.exists()){Queue<File> queue = new LinkedList<>();queue.add(file);while(!queue.isEmpty()){File poll = queue.poll();if(poll == null){continue;}if(poll.isDirectory()){File[] files = poll.listFiles();for (File f : files) {queue.add(f);}}else {filePaths.add(poll.getPath());}}}else {throw new FileNotFoundException(basePath+" not found");}//将路径中所有的文件打印出来 filePaths.forEach(e-> System.out.println(e));}/*** 讲所有的.java结尾的 全限定名放到 beanNames*/public void  initBeanNames(){for (String s : filePaths) {String replace = s.replace(basePath, "");if(replace.endsWith(".java")) {replace = replace.substring(0, replace.length()-5);}char[] chars = replace.toCharArray();for (int i = 0; i < chars.length; i++) {if(chars[i]=='\\'){chars[i] = '.';}}beanNames.add(basePackage+"."+new String(chars));}beanNames.forEach(System.out::println);}public void initBeans(){for (String beanName : beanNames) {try {Class<?> aClass = Class.forName(beanName);Annotation[] declaredAnnotations = aClass.getDeclaredAnnotations();for (Annotation declaredAnnotation : declaredAnnotations) {if(declaredAnnotation instanceof Component){//反射:Object o = aClass.newInstance();beans.put(aClass.getName(),o);}}} catch (ClassNotFoundException | InstantiationException | IllegalAccessException e) {e.printStackTrace();}}for (Map.Entry<String, Object> entry : beans.entrySet()) {Field[] declaredFields = entry.getValue().getClass().getDeclaredFields();for (Field field : declaredFields) {Annotation[] declaredAnnotations = field.getDeclaredAnnotations();for (Annotation annotation : declaredAnnotations) {if(annotation instanceof Autowired){//field 需要由我们来赋值// 我们所持有的所有对象 在beans中// 根据当前域中的类型的名字:反射String name = field.getType().getName();// 从beans 中获得对应的对象Object o = beans.get(name);field.setAccessible(true);try {field.set(entry.getValue(), o);} catch (IllegalAccessException e) {e.printStackTrace();}}}}}}public Object getInstance(String beanName) {return beans.get(beanName);}private void initPath(){basePath="D:\\imitateIOC\\src\\main\\java\\com\\test\\springioc\\";basePackage="com.test.springioc";}public SpringIOC() {initPath();try {scan();} catch (FileNotFoundException e) {e.printStackTrace();}beanNames= new ArrayList<>();initBeanNames();}
}

Autowired和Component注解

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Autowired {
}@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Component {
}

SpringIOCTest 类 

public class SpringIOCTest {@Testpublic void testIOC() throws FileNotFoundException {//创建IOC容器SpringIOC springIOC = new SpringIOC();//初始化容器springIOC.initBeans();//从容器中获得TestController对象TestController instance = (TestController) springIOC.getInstance(TestController.class.getName());//调用其方法instance.test();}
}

总结:

整个环境可以归纳为两个阶段:

第一阶段:处理字符串,获得到类权限的名

第二阶段:根据类权限名创建对应的对象(带有@Component的类才会创建对应的对象),然后再遍历访问我们创建好的对象,判断所有的域是否带有@Autowired,如果有就从Bean中取出对应的对象设置进去。

通篇我们没有写new TestController,new UserService这种代码,都是由反射创建的对象设置进来,这就是这篇代码的基本逻辑。

源码已上传gitee平台:

https://gitee.com/dont-live-in-the-past/copy-ioc.git


相关文章:

仿写简单IOC

目录 TestController类: UserService类: 核心代码SpringIOC&#xff1a; Autowired和Component注解 SpringIOCTest 类 ​编辑 总结&#xff1a; TestController类: Component public class TestController {Autowiredprivate UserService userService;public void test…...

liunx下安装node exporter

1 建立文件夹 cd /opt mkdir software 下载最新的包&#xff0c;并解压 https://prometheus.io/download/ 下载 curl -LO https://github.com/prometheus/node_exporter/releases/download/v0.18.1/node_exporter-0.18.1.linux-amd64.tar.gz 3.解压 tar -xvf node_exporter-0.…...

lambda函数

Lambda(函数指针)lambda 是c11非常重要也是最常用的特性之一&#xff0c;他有以下优点&#xff1a;可以就地匿名定义目标函数或函数对象&#xff0c;不需要额外写一个函数lambda表达式是一个匿名的内联函数lambda表达式定义了一个匿名函数&#xff0c;语法如下&#xff1a;[cap…...

【Python入门第二十七天】Python 日期

Python 日期 Python 中的日期不是其自身的数据类型&#xff0c;但是我们可以导入名为 datetime 的模块&#xff0c;把日期视作日期对象进行处理。 实例 导入 datetime 模块并显示当前日期&#xff1a; import datetimex datetime.datetime.now() print(x)运行实例 2023-0…...

C++基础知识【5】数组和指针

目录 一、概述 数组 指针 二、数组 2.1、数组的声明 2.2、数组的初始化 2.3、数组的访问 2.4、多维数组 2.5、数组作为函数参数 三、指针 3.1、指针的声明 3.2、指针的赋值 3.3、指针的访问 3.4、指针运算 3.5、指针数组和数组指针 3.6、二级指针 四、数组和指…...

Vim使用操作命令笔记

Vim使用操作命令笔记在普通模式下&#xff0c;输入 : help tutor 就可以进入vim的教学       在 terminal 中输入 vim 文件名 就可以打开文件    vim有两种模式   normal mode &#xff08;普通模式&#xff09;→ 指令操作   insert mode &#xff08;输入模式&…...

【论文阅读】Robust Multi-Instance Learning with Stable Instances

1、摘要与引言 以往的MIL算法遵循i.i.d假设&#xff1a;训练样本与测试样本都分别来自于同一分布中&#xff0c;而这一假设往往与现实应用中有所出入。研究人员通过计算训练样本与测试样本之间的密度比对训练样本进行加权&#xff0c;以解决分布变化带来的问题。 分布的变化发…...

洛谷 P5116 [USACO18DEC]Mixing Milk B

题目链接&#xff1a;P5116 [USACO18DEC]Mixing Milk B - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 题目描述 农业&#xff0c;尤其是生产牛奶&#xff0c;是一个竞争激烈的行业。Farmer John 发现如果他不在牛奶生产工艺上有所创新&#xff0c;他的乳制品生意可能就会受…...

华为OD机试 - 最左侧冗余覆盖子串(C 语言解题)【独家】

最近更新的博客 华为od 2023 | 什么是华为od,od 薪资待遇,od机试题清单华为OD机试真题大全,用 Python 解华为机试题 | 机试宝典【华为OD机试】全流程解析+经验分享,题型分享,防作弊指南)华为od机试,独家整理 已参加机试人员的实战技巧文章目录 使用说明本期题目:最左侧冗…...

《Netty》从零开始学netty源码(三)之SelectorProvider

...

实验7 图像水印

本次实验大部分素材来源于山大王成优老师的讲义以及冈萨雷斯&#xff08;MATLAB版&#xff09;&#xff0c;仅作个人学习笔记使用&#xff0c;禁止用作商业目的。 文章目录一、实验目的二、实验例题1. 数字图像水印技术2. 可见水印的嵌入3. 不可见脆弱水印4. 不可见鲁棒水印一、…...

如何实现大文件断点续传、秒传

大家先来了解一下几个概念&#xff1a; 「文件分块」&#xff1a;将大文件拆分成小文件&#xff0c;将小文件上传\下载&#xff0c;最后再将小文件组装成大文件&#xff1b; 「断点续传」&#xff1a;在文件分块的基础上&#xff0c;将每个小文件采用单独的线程进行上传\下载&…...

备战蓝桥python——完全平方数

完全平方数 链接: 完全平方数 暴力解法&#xff1a; n int(input()) for i in range(1, n1):if(((i*n)**0.5)%10.0):print(i)break运用数论相关知识求解 任意一个正整数都可以被分解成若干个质数乘积的形式&#xff0c;例如 :2022∗5120 \ 2^{2}*5^{1}\,20 22∗51 由此…...

WebRTC中的NAT穿透

NAT简介 我们知道&#xff0c;WebRTC会按照内网、P2P、中转的顺序来尝试连接。在大部分的情况下&#xff0c;实际是使用P2P或者中转的。这里P2P的场景主要使用的技术就是NAT穿透。 我们先简单了解下NAT。NAT在真实网络中是常见的&#xff0c;它的出现一是为了解决ipv4地址不够…...

SpringCloud-高级篇(一)

目录&#xff1a; &#xff08;1&#xff09;初识Sentinel-雪崩问题的解决方案 &#xff08;2&#xff09;服务保护Sentinel和Hystrix对比 &#xff08;3&#xff09;Sentinel初始-安转控制台 &#xff08;4&#xff09;整合微服务和Sentinel 微服务高级篇 &#xff08;1&…...

电脑自动重启是什么原因?详细解说

案例&#xff1a;电脑自动重启是什么原因&#xff1f; “一台用了一年的电脑&#xff0c;最近使用&#xff0c;每天都会一两次莫名其妙自动重启&#xff0c;看了电脑错误日志&#xff0c;看不懂什么意思&#xff0c;一直找不到答案。有没有高手知道怎么解决这个问题的。” 当…...

2023美国大学生数学建模竞赛E题思路

problem 背景&#xff1a; 光污染用于描述过度或不良使用人造光。我们称之为光污染的一些现象包括光侵入、过度照明和光杂波。在大城市&#xff0c;太阳落山后&#xff0c;这些现象最容易在天空中看到:然而&#xff0c;它们也可能发生在更偏远的地区。 光污染会改变我们对夜空…...

蓝桥杯三月刷题 第五天

文章目录&#x1f4a5;前言&#x1f609;解题报告&#x1f4a5;数的分解&#x1f914;一、思路:&#x1f60e;二、代码&#xff1a;&#x1f4a5;前言 上午没写&#xff0c;下午写了会被朋友拉出去耍&#xff0c;被冷风吹到了&#xff0c;而且被他坑了&#xff0c;根本没有玩骑…...

Echarts 水波图实现

开发的项目中需要实现这样一个水波图&#xff0c;例如下图在echarts官网中找了很久没找到&#xff0c;后面是在Echarts社区中找到的&#xff0c;实现了大部分的样式&#xff0c;但是还有一些数据的展示没有实现。水波图的数值展示是默认整数百分比&#xff0c;我的需求是需要保…...

逻辑优化基础-shannon decomposition

1. 简介 在逻辑综合中&#xff0c;香农分解&#xff08;Shannon decomposition&#xff09;是一种常用的布尔函数分解方法。它将一个布尔函数分解为两个子函数的和&#xff0c;其中每个子函数包含一个布尔变量的取反和非取反的部分。 具体来说&#xff0c;假设对于一个布尔函…...

rknn优化教程(二)

文章目录 1. 前述2. 三方库的封装2.1 xrepo中的库2.2 xrepo之外的库2.2.1 opencv2.2.2 rknnrt2.2.3 spdlog 3. rknn_engine库 1. 前述 OK&#xff0c;开始写第二篇的内容了。这篇博客主要能写一下&#xff1a; 如何给一些三方库按照xmake方式进行封装&#xff0c;供调用如何按…...

Admin.Net中的消息通信SignalR解释

定义集线器接口 IOnlineUserHub public interface IOnlineUserHub {/// 在线用户列表Task OnlineUserList(OnlineUserList context);/// 强制下线Task ForceOffline(object context);/// 发布站内消息Task PublicNotice(SysNotice context);/// 接收消息Task ReceiveMessage(…...

《从零掌握MIPI CSI-2: 协议精解与FPGA摄像头开发实战》-- CSI-2 协议详细解析 (一)

CSI-2 协议详细解析 (一&#xff09; 1. CSI-2层定义&#xff08;CSI-2 Layer Definitions&#xff09; 分层结构 &#xff1a;CSI-2协议分为6层&#xff1a; 物理层&#xff08;PHY Layer&#xff09; &#xff1a; 定义电气特性、时钟机制和传输介质&#xff08;导线&#…...

MMaDA: Multimodal Large Diffusion Language Models

CODE &#xff1a; https://github.com/Gen-Verse/MMaDA Abstract 我们介绍了一种新型的多模态扩散基础模型MMaDA&#xff0c;它被设计用于在文本推理、多模态理解和文本到图像生成等不同领域实现卓越的性能。该方法的特点是三个关键创新:(i) MMaDA采用统一的扩散架构&#xf…...

srs linux

下载编译运行 git clone https:///ossrs/srs.git ./configure --h265on make 编译完成后即可启动SRS # 启动 ./objs/srs -c conf/srs.conf # 查看日志 tail -n 30 -f ./objs/srs.log 开放端口 默认RTMP接收推流端口是1935&#xff0c;SRS管理页面端口是8080&#xff0c;可…...

C++使用 new 来创建动态数组

问题&#xff1a; 不能使用变量定义数组大小 原因&#xff1a; 这是因为数组在内存中是连续存储的&#xff0c;编译器需要在编译阶段就确定数组的大小&#xff0c;以便正确地分配内存空间。如果允许使用变量来定义数组的大小&#xff0c;那么编译器就无法在编译时确定数组的大…...

基于 TAPD 进行项目管理

起因 自己写了个小工具&#xff0c;仓库用的Github。之前在用markdown进行需求管理&#xff0c;现在随着功能的增加&#xff0c;感觉有点难以管理了&#xff0c;所以用TAPD这个工具进行需求、Bug管理。 操作流程 注册 TAPD&#xff0c;需要提供一个企业名新建一个项目&#…...

C++课设:简易日历程序(支持传统节假日 + 二十四节气 + 个人纪念日管理)

名人说:路漫漫其修远兮,吾将上下而求索。—— 屈原《离骚》 创作者:Code_流苏(CSDN)(一个喜欢古诗词和编程的Coder😊) 专栏介绍:《编程项目实战》 目录 一、为什么要开发一个日历程序?1. 深入理解时间算法2. 练习面向对象设计3. 学习数据结构应用二、核心算法深度解析…...

4. TypeScript 类型推断与类型组合

一、类型推断 (一) 什么是类型推断 TypeScript 的类型推断会根据变量、函数返回值、对象和数组的赋值和使用方式&#xff0c;自动确定它们的类型。 这一特性减少了显式类型注解的需要&#xff0c;在保持类型安全的同时简化了代码。通过分析上下文和初始值&#xff0c;TypeSc…...

React从基础入门到高级实战:React 实战项目 - 项目五:微前端与模块化架构

React 实战项目&#xff1a;微前端与模块化架构 欢迎来到 React 开发教程专栏 的第 30 篇&#xff01;在前 29 篇文章中&#xff0c;我们从 React 的基础概念逐步深入到高级技巧&#xff0c;涵盖了组件设计、状态管理、路由配置、性能优化和企业级应用等核心内容。这一次&…...