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

自己写一个简单的IOC

什么是SpringIOC?
答:IOC即控制反转,就是我们不在手动的去new一个对象,而是将创建对象的权力交给Spring去管理,我们想要一个User类型的对象,就只需要定义一个User类型的变量user1,然后让Spring去给我们创建对象,然后将创建的对象注入到user1中。
什么是依赖注入?
答:DI机制(DependencyInjection),依赖注入,上面提到的Spring将它创建的对象交给我们创建的变量的过程。依赖注入的方式有三种(set方法注入、构造器注入、注解注入)。下面我们简答的实现注解注入,了解IOC原理。

第一步,创建注解

创建的注解其实没有太大的作用,就是用来标记哪个类需要Spring帮我们去管理,哪个成员变量需要Spring去给我们注入。

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
*创建注解文件Component.java
*标记需要IOC的类
**/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Component {
}
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
*创建注解文件Autowired.java
*标记需要Spring帮忙DI的成员变量
**/
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Autowired {
}

第二部,创建两个需要注解的类

我们想要将MyService和MyController都交给Spring管理(项目启动后将这两个类实例化,然后放入一个HashMap中,等待调用)
在这里插入图片描述

import com.xiaoran.springioc.annotation.Component;
@Component
public class MyService {private int id;private String name;private int age;public void speck(String name,int age) {System.out.println("大家好,我叫"+name+"今年"+age+"岁了,请多多关照!");}
}
import com.xiaoran.springioc.annotation.Autowired;
import com.xiaoran.springioc.annotation.Component;
@Component
public class MyController {@Autowiredprivate MyService myService;public void test(){myService.speck("moss",67);}
}

第三步,IOC过程

创建MyIOC类,用于IOC过程

  • 在项目启动时,实例化MyIOC,加载MyIOC的无参构造器时,对项目下所有的文件进行扫描,调用实例化方法完成被注释类的实例化和依赖注入。
    private String basePath="D:\\Project\\XiaoRanIOC\\src\\main\\java\\com\\xiaoran\\springioc\\";  //项目路径private String basePackage="com.xiaoran.springioc"; //包路径private List<String> filePaths;//所有文件的路径private List<String> beanNames;//所有.java文件的全限定名private Map<String, Object> beans = new HashMap<>();/*** 实例化MyIOC时,让IOC进程伴随无参构造器加载启动*/public MyIOC() throws FileNotFoundException, IllegalAccessException {//扫描路径下所有文件scan();beanNames = new ArrayList<>();initBeanNames();initBeans();}
  • 扫描项目下所有文件,将所有文件的路径存入filePaths中
/*** 扫描项目下所有文件,将所有文件的路径存入filePaths中*/public void scan() throws FileNotFoundException {File file = new File(basePath);filePaths=new ArrayList<>();if (file.exists()) {//将file放入列,出队后判断,如果是路径那就继续入队,如果是文件,就将文件路径放入filePaths中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 + "不存在");}}
  • 将所有的.java文件的全限定名放入beanNames中
/***将所有的.java文件的全限定名放入beanNames中*/public void initBeanNames(){for (String string :filePaths) {String replace = string.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));}}
  • 核心代码:将被@Component注解的类实例化放入beans(HashMap)中,等待调用
   /***核心代码:将被@Component注解的类实例化放入beans(HashMap)中,等待调用*/public void initBeans() throws IllegalAccessException {//遍历包路径下所有类,是否被@Component注解,如果被注解就将其实例化放入beansfor (String beanName :beanNames) {try {Class<?> aClass = Class.forName(beanName);//获取类的所有注解Annotation[] declaredAnnotation = aClass.getDeclaredAnnotations();//遍历所有注解,是否是@Component注解for (Annotation annotation :declaredAnnotation) {if (annotation instanceof Component){Object o = aClass.newInstance();beans.put(beanName, o);}}} catch (ClassNotFoundException e) {e.printStackTrace();} catch (IllegalAccessException e) {e.printStackTrace();} catch (InstantiationException e) {e.printStackTrace();}}//遍历所有的beans的成员变量,如果有成员变量被@Autowired修饰,就根据成员变量的类型从beans中查找到对应的对象,用此对象给成员变量注入//因为是从beans中查找对象,所以被注入的成员变量对应的类一定是已经被实例化放入beans中的for (Map.Entry<String, Object> entry : beans.entrySet()) {Object value = entry.getValue();Field[] fields = value.getClass().getDeclaredFields();for (Field f :fields) {Annotation[] declaredAnnotations = f.getDeclaredAnnotations();for (Annotation annotation :declaredAnnotations) {if (annotation instanceof Autowired){//获取被@Autowired注解成员变量的类型(全限定名)String typeName = f.getType().getName();Object o = beans.get(typeName);//暴力反射f.setAccessible(true);//将从beans中获得的对象o,注入到该属性上f.set(value,o);}}}}}/*** 对外提供一个方法:根据全限定名返回对象*/public Object getInstance(String beanName){return beans.get(beanName);}

第四步,测试

创建测试类IOCTest

import com.xiaoran.springioc.entity.MyController;
import com.xiaoran.springioc.ioc.MyIOC;
import org.junit.Test;
import java.io.FileNotFoundException;
public class IOCTest {@Testpublic void test() throws FileNotFoundException, IllegalAccessException {MyIOC myIOC = new MyIOC();MyController myController = (MyController)myIOC.getInstance(MyController.class.getName());myController.test();}
}

GitHub

手撕SpringIOC

相关文章:

自己写一个简单的IOC

什么是SpringIOC&#xff1f; 答&#xff1a;IOC即控制反转&#xff0c;就是我们不在手动的去new一个对象&#xff0c;而是将创建对象的权力交给Spring去管理&#xff0c;我们想要一个User类型的对象&#xff0c;就只需要定义一个User类型的变量user1&#xff0c;然后让Spring去…...

用Python批量重命名文件

案例 今天,我们来整理文件夹中的文件,给某个文件夹下的所有文件重新命名。要求是给所有文件按照修改时间,按顺序在文件名前面加上编号。比如将文件资料.xlsx重命名为1. 资料.xlsx import osdef Get_modify_time(file):return os.path.getmtime(file) #获取文件修改时间path…...

iis之web服务器搭建、部署(详细)~千锋

目录 Web服务器 部署web服务器 实验一 发布一个静态网站 实验二 一台服务器同时发布多个web站点 网站类型 Web服务器 也叫网页服务或HTTP服务器web服务器使用的协议是HTTPHTTP协议端口号&#xff1a;TCP 80、HTTPS协议端口号&#xff1a;TCP 443Web服务器发布软件&…...

javascript的ajax

学什么Ajax基础JSON跨域XHR对象Ajax进阶Ajax应用Ajax扩展Ajax基础初识 AjaxAjax的基本用法GET请求POST请求JSON初识JSONJSON的3种形式JSON的常用方法跨域初识跨域CORS跨域资源共享JSONPXHR 对象XHR的属性XHR的方法XHR的事件Ajax进阶FormData封装Ajax使用Promise改造封装好的Aja…...

SpringBoot入门 - 开发中还有哪些常用注解

本文主要介绍一些SpringBoot中常用的注解。Spring Boot 常用注解SpringBootApplicationTarget(ElementType.TYPE) Retention(RetentionPolicy.RUNTIME) Documented Inherited Configuration EnableAutoConfiguration ComponentScan public interface SpringBootApplication {/*…...

网络基础(三)

目录 网络层与数据链路层 ​编辑 网络层 IP协议 IP的构成 TCP和IP各自解决什么问题&#xff1f; 基本概念 协议头格式 协议头分析 如何分离与封装&#xff1f; 如何分用(向上交付)&#xff1f; 16位首部校验和 32位源IP和目的IP 4位版本 8位服务类型(Type Of…...

Go语言函数高级篇

Go语言函数高级篇1.高阶函数函数作为参数函数作为返回值2.匿名函数3.defer4.内置函数1.高阶函数 高阶函数分为函数作为参数和函数作为返回值两部分。 函数作为参数 函数可以作为参数&#xff1a; package mainimport "fmt"func add(x, y int) int {return x y }…...

ubuntu16.04 python代码自启动和可执行文件自启动

1 python代码自启动 参考 https://blog.csdn.net/qq_38288618/article/details/104096606 准备好python文件 test.py import time c1 while 1:time.sleep(1)cc1print(c)运行 sudo chmod 777 test.py python3 test.py准备run.sh 文件 #!/bin/bash gnome-terminal -x bash -…...

应用层协议 HTTP HTTPS

目录 应用层 再谈 "协议" 序列化和反序列化 关于 json库 request序列化 request反序列化 response序列化 response反序列化 PS&#xff1a;命令宏 HTTP协议 认识URL urlencode和urldecode HTTP协议格式 HTTP请求 HTTP响应 请求方法 ​编辑 HT…...

图神经网络 pytorch GCN torch_geometric KarateClub 数据集

图神经网络 安装Pyg 首先安装torch_geometric需要安装pytorch然后查看一下自己电脑Pytorch的版本 import torch print(torch.__version__) #1.12.0cu113然后进入官网文档网站 链接: https://pytorch-geometric.readthedocs.io/en/latest/install/installation.html 安装自己…...

【博学谷学习记录】超强总结,用心分享丨人工智能 自然语言处理 文本特征处理小结

目录文本特征处理作用常见的文本特征处理方法添加n-gram特征说明提取n-gram文本长度规范说明实现导包问题记录心得文本特征处理作用 文本特征处理包括为语料添加具有普适性的文本特征, 如:n-gram特征 以及对加入特征之后的文本语料进行必要的处理, 如: 长度规范. 这些特征处…...

2023年中职网络安全竞赛解析——隐藏信息探索

隐藏信息探索 需求环境可私信博主,求个三连! 1.访问服务器的FTP服务,下载图片QR,从图片中获取flag,并将flag提交; 2.访问服务器的FTP服务,下载文件document,从文件中获取flag,并将flag提交; 3.访问服务器的FTP服务,下载图片beach,从图片中获取flag,并将flag提交…...

实用操作--迁移到Spring Boot 3 和 Spring 6 需要关注的JAVA新特性

正如你所了解到的,迁移到Spring Boot 3 或 Spring 6也将迁移到Java 17和Jakarta EE 9。 如果你非常重视可观察性和本机可执行文件,将从Spring Boot 和 Spring 的主要发行版中获益最大。 本文针对迁移到Spring Boot 3 或 Spring 6涉及的变化进行了梳理和总结。 1. java17新特…...

等保检测风险处理方案

文章目录等保检测风险处理方案1. Apache HTTP Server "httpOnly" Cookie信息泄露漏洞(CVE-2012-0053))2. 检测到目标web应用表单存在口令猜测攻击3. X-Content-Type-Options响应头缺失4. X-XSS-Protection响应头缺失5. Content-Security-Policy响应头缺失6. Referrer…...

java 包装类 万字详解(通俗易懂)

前言简介和溯源拆装箱String类和基本类型的相互转化String类和包装类型的相互转化八大包装类的常用方法汇总&#xff08;含代码演示&#xff09;一、前言 : 本节内容是我们《API-常用类》专题的最后一节了。本节内容主要讲包装类&#xff0c;内容包括但不限于包装类的诞生&…...

为什么我复制的中文url粘贴出来会是乱码的? 浏览器url编码和解码

为什么我复制的中文url粘贴出来会是乱码的&#xff1f; 浏览器url编码和解码 Start 番茄最近涉及到一些和单点登录相关的业务需求&#xff0c;在实现功能的过程中&#xff0c;难免少不了和 url 打交道。但是在打交道的过程中&#xff0c;遇到一个痛点&#xff1a;明明我复制的…...

移动端适配

​ 是看的b站一个老哥的视频&#xff0c;做的汇总&#xff0c;讲的嘎嘎棒。视频链接&#xff1a;b站链接 视口viewport pc端视口就是可视化的窗口&#xff0c;不包含浏览器工具栏但是移动端&#xff0c;不太一样&#xff0c;布局的视口和可见的视口是不太一样的 移动端的网页…...

【FPGA】Verilog:时序电路应用 | 序列发生器 | 序列检测器

前言&#xff1a;本章内容主要是演示Vivado下利用Verilog语言进行电路设计、仿真、综合和下载 示例&#xff1a;序列发生器与序列检测器 ​ 功能特性&#xff1a; 采用 Xilinx Artix-7 XC7A35T芯片 配置方式&#xff1a;USB-JTAG/SPI Flash 高达100MHz 的内部时钟速度 存储器…...

Biomod2 (下):物种分布模型建模

这里写目录标题1.给出一个线性回归模型并求出因子贡献度2.biomod22.1 pseudo-absences:伪不存在点&#xff08;PA&#xff09;2.1.1 random2.2.2 disk2.2.3 user.defined method3.使用网格划分区域3.1 计算质心4. 完整案例1.给出一个线性回归模型并求出因子贡献度 ##---------…...

Linux性能学习(2.2):内存_进程线程内存分配机制探究

文章目录1 进程内存分配探究1.1 代码1.2 试验过程2 线程内存分配探究2.1 代码2.2 试验过程3 总结参考资料&#xff1a;1. 嵌入式软件开发杂谈&#xff08;3&#xff09;&#xff1a;Linux下内存与虚拟内存2. 嵌入式软件开发杂谈&#xff08;1&#xff09;&#xff1a;Linux下最…...

Cursor实现用excel数据填充word模版的方法

cursor主页&#xff1a;https://www.cursor.com/ 任务目标&#xff1a;把excel格式的数据里的单元格&#xff0c;按照某一个固定模版填充到word中 文章目录 注意事项逐步生成程序1. 确定格式2. 调试程序 注意事项 直接给一个excel文件和最终呈现的word文件的示例&#xff0c;…...

Flask RESTful 示例

目录 1. 环境准备2. 安装依赖3. 修改main.py4. 运行应用5. API使用示例获取所有任务获取单个任务创建新任务更新任务删除任务 中文乱码问题&#xff1a; 下面创建一个简单的Flask RESTful API示例。首先&#xff0c;我们需要创建环境&#xff0c;安装必要的依赖&#xff0c;然后…...

k8s从入门到放弃之Ingress七层负载

k8s从入门到放弃之Ingress七层负载 在Kubernetes&#xff08;简称K8s&#xff09;中&#xff0c;Ingress是一个API对象&#xff0c;它允许你定义如何从集群外部访问集群内部的服务。Ingress可以提供负载均衡、SSL终结和基于名称的虚拟主机等功能。通过Ingress&#xff0c;你可…...

生成 Git SSH 证书

&#x1f511; 1. ​​生成 SSH 密钥对​​ 在终端&#xff08;Windows 使用 Git Bash&#xff0c;Mac/Linux 使用 Terminal&#xff09;执行命令&#xff1a; ssh-keygen -t rsa -b 4096 -C "your_emailexample.com" ​​参数说明​​&#xff1a; -t rsa&#x…...

【配置 YOLOX 用于按目录分类的图片数据集】

现在的图标点选越来越多&#xff0c;如何一步解决&#xff0c;采用 YOLOX 目标检测模式则可以轻松解决 要在 YOLOX 中使用按目录分类的图片数据集&#xff08;每个目录代表一个类别&#xff0c;目录下是该类别的所有图片&#xff09;&#xff0c;你需要进行以下配置步骤&#x…...

【学习笔记】深入理解Java虚拟机学习笔记——第4章 虚拟机性能监控,故障处理工具

第2章 虚拟机性能监控&#xff0c;故障处理工具 4.1 概述 略 4.2 基础故障处理工具 4.2.1 jps:虚拟机进程状况工具 命令&#xff1a;jps [options] [hostid] 功能&#xff1a;本地虚拟机进程显示进程ID&#xff08;与ps相同&#xff09;&#xff0c;可同时显示主类&#x…...

零基础在实践中学习网络安全-皮卡丘靶场(第九期-Unsafe Fileupload模块)(yakit方式)

本期内容并不是很难&#xff0c;相信大家会学的很愉快&#xff0c;当然对于有后端基础的朋友来说&#xff0c;本期内容更加容易了解&#xff0c;当然没有基础的也别担心&#xff0c;本期内容会详细解释有关内容 本期用到的软件&#xff1a;yakit&#xff08;因为经过之前好多期…...

技术栈RabbitMq的介绍和使用

目录 1. 什么是消息队列&#xff1f;2. 消息队列的优点3. RabbitMQ 消息队列概述4. RabbitMQ 安装5. Exchange 四种类型5.1 direct 精准匹配5.2 fanout 广播5.3 topic 正则匹配 6. RabbitMQ 队列模式6.1 简单队列模式6.2 工作队列模式6.3 发布/订阅模式6.4 路由模式6.5 主题模式…...

宇树科技,改名了!

提到国内具身智能和机器人领域的代表企业&#xff0c;那宇树科技&#xff08;Unitree&#xff09;必须名列其榜。 最近&#xff0c;宇树科技的一项新变动消息在业界引发了不少关注和讨论&#xff0c;即&#xff1a; 宇树向其合作伙伴发布了一封公司名称变更函称&#xff0c;因…...

WebRTC从入门到实践 - 零基础教程

WebRTC从入门到实践 - 零基础教程 目录 WebRTC简介 基础概念 工作原理 开发环境搭建 基础实践 三个实战案例 常见问题解答 1. WebRTC简介 1.1 什么是WebRTC&#xff1f; WebRTC&#xff08;Web Real-Time Communication&#xff09;是一个支持网页浏览器进行实时语音…...