自己写一个简单的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? 答:IOC即控制反转,就是我们不在手动的去new一个对象,而是将创建对象的权力交给Spring去管理,我们想要一个User类型的对象,就只需要定义一个User类型的变量user1,然后让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协议端口号:TCP 80、HTTPS协议端口号: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各自解决什么问题? 基本概念 协议头格式 协议头分析 如何分离与封装? 如何分用(向上交付)? 16位首部校验和 32位源IP和目的IP 4位版本 8位服务类型(Type Of…...

Go语言函数高级篇
Go语言函数高级篇1.高阶函数函数作为参数函数作为返回值2.匿名函数3.defer4.内置函数1.高阶函数 高阶函数分为函数作为参数和函数作为返回值两部分。 函数作为参数 函数可以作为参数: 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:命令宏 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类和包装类型的相互转化八大包装类的常用方法汇总(含代码演示)一、前言 : 本节内容是我们《API-常用类》专题的最后一节了。本节内容主要讲包装类,内容包括但不限于包装类的诞生&…...

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

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

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

Biomod2 (下):物种分布模型建模
这里写目录标题1.给出一个线性回归模型并求出因子贡献度2.biomod22.1 pseudo-absences:伪不存在点(PA)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 总结参考资料:1. 嵌入式软件开发杂谈(3):Linux下内存与虚拟内存2. 嵌入式软件开发杂谈(1):Linux下最…...
<6>-MySQL表的增删查改
目录 一,create(创建表) 二,retrieve(查询表) 1,select列 2,where条件 三,update(更新表) 四,delete(删除表…...
rknn优化教程(二)
文章目录 1. 前述2. 三方库的封装2.1 xrepo中的库2.2 xrepo之外的库2.2.1 opencv2.2.2 rknnrt2.2.3 spdlog 3. rknn_engine库 1. 前述 OK,开始写第二篇的内容了。这篇博客主要能写一下: 如何给一些三方库按照xmake方式进行封装,供调用如何按…...
反向工程与模型迁移:打造未来商品详情API的可持续创新体系
在电商行业蓬勃发展的当下,商品详情API作为连接电商平台与开发者、商家及用户的关键纽带,其重要性日益凸显。传统商品详情API主要聚焦于商品基本信息(如名称、价格、库存等)的获取与展示,已难以满足市场对个性化、智能…...
R语言AI模型部署方案:精准离线运行详解
R语言AI模型部署方案:精准离线运行详解 一、项目概述 本文将构建一个完整的R语言AI部署解决方案,实现鸢尾花分类模型的训练、保存、离线部署和预测功能。核心特点: 100%离线运行能力自包含环境依赖生产级错误处理跨平台兼容性模型版本管理# 文件结构说明 Iris_AI_Deployme…...

visual studio 2022更改主题为深色
visual studio 2022更改主题为深色 点击visual studio 上方的 工具-> 选项 在选项窗口中,选择 环境 -> 常规 ,将其中的颜色主题改成深色 点击确定,更改完成...
Golang dig框架与GraphQL的完美结合
将 Go 的 Dig 依赖注入框架与 GraphQL 结合使用,可以显著提升应用程序的可维护性、可测试性以及灵活性。 Dig 是一个强大的依赖注入容器,能够帮助开发者更好地管理复杂的依赖关系,而 GraphQL 则是一种用于 API 的查询语言,能够提…...

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,SRS管理页面端口是8080,可…...
拉力测试cuda pytorch 把 4070显卡拉满
import torch import timedef stress_test_gpu(matrix_size16384, duration300):"""对GPU进行压力测试,通过持续的矩阵乘法来最大化GPU利用率参数:matrix_size: 矩阵维度大小,增大可提高计算复杂度duration: 测试持续时间(秒&…...
数据库分批入库
今天在工作中,遇到一个问题,就是分批查询的时候,由于批次过大导致出现了一些问题,一下是问题描述和解决方案: 示例: // 假设已有数据列表 dataList 和 PreparedStatement pstmt int batchSize 1000; // …...

Android15默认授权浮窗权限
我们经常有那种需求,客户需要定制的apk集成在ROM中,并且默认授予其【显示在其他应用的上层】权限,也就是我们常说的浮窗权限,那么我们就可以通过以下方法在wms、ams等系统服务的systemReady()方法中调用即可实现预置应用默认授权浮…...