自己造一个简易的IOC轮子

2023-10-27

简易的IOC流程编写笔记

首先先对这个小demo做一个说明。首先这个demo是很简易的,里面有一些可以优化的复杂点我设置了TODO,如果你有兴趣的话,可以自己去完善一下,写这个demo就是为了让自己对IOC的一个流程更加熟悉,对于刚开始学习Spring IOC的小伙伴来说学一下还是好的,可以帮助我们理解流程,为以后看源码做铺垫。编写是参考了Spring的源码中的流程。

大概的流程是这样的:

​ 自定义了两个注解,@Be、@Di注解,其中@Be注解的作用和spring中的@Component、@Repository、@Service、@Controller类似,就是将当前这个类定义为Bean,对这个对象进行一个实例化。参考spring的源码,spring源码中,实例化的对象放到了一个map集合中,这个map的结构是这样的.所以根据这个我也使用了一个map来存放实例化后的对象。我自定的map结构是map<class,Object>,key是它对应的类,value是这个对象。于此对应的我们可以通过class来得到object。

Map<String, BeanDefinition> beanDefinitionMap=new ConcurrentHashMap<>(256);

然后我们在使用原生的spring的时候我们一般都是通过ApplicationContext这个应用上下文来得到对应的Bean,调用它的getBean方法,spring中ApplicationContext是一个接口,里面的实现类有

我们经常使用的是ClassPathXmlApplicationContext来获取xml中的配置,或者是使用AnnotationConfigApplicationContext来获取配置文件中的配置。基于这个我也写了一个ApplicationContext接口,在这个接口中只有一个getBean方法,就是通过class类来获取对应的object

public interface ApplicationContext {
    //这个接口就是仿照spring原生的ApplicationContext接口来写的,这个接口中有个方法来根据类返回对应的对象
     public Object getBean(Class clazz);
}

实现类就是整个流程中最关键也是最核心的一个类了,在这个类中完成了getBean(),以及是如何将类上的@Be注解对应的类实例化的,以及如何将@Di对应的属性进行注入的。

对@Be标注的类进行实例化的流程大致如下:

​ 1、我们定义一个构造方法,这个构造方法中传过来一个对应的包的全类名。类似于spring中的ClassPathXmlApplicationContext一样。

​ 2、通过传过来的这个全类名,我们直到去哪个包以及这个包下面的所有子包中扫描所有的.class文件,然后将标注了@Be的.class文件进行实例化,当然里面还有很多注意的地方,下面会细说。

​ 3、在Java中全类名的书写格式是这样的“com.lyq”,以".“分割的,因为我们要去操作系统的文件中去获取对应的文件,所以这个格式肯定是不对的,所以我们需要对这个格式进行一个转义,将“.”替换成”\",这个过程要注意转义。

​ 4、然后通过当前线程可以获得这个包对应的绝对路径,因为我们一个项目中的前面的路径都是一样的,所以我用了一个全局变量rootPath来存放前面公共的部分。然后我们通过文件流去操作这个对应的绝对路径。

​ 5、如果对应的这个文件是不是一个文件夹的话,其实是不合法的,说明传过来的包就错了, 所以不处理。当这个文件是一个文件夹的话进行接下来的处理。

​ 6、去遍历这个文件夹下的所有的文件,因为我们要扫描这个包以及下面的所有子包中标注了@Be的类。然后对于它所有的子文件,如果这个子文件是一个文件夹的话我们就去递归扫描执行。然后是一个文件的话,我们还要判断是不是一个.class文件,因为我们操作的是一个类,所以必须是.class文件。

​ 7、如果这个文件是一个.class文件了,我们要去实例化的时候我们又要通过反射,所以这里我们又要将这个“com\lyq”这种格式的路径转成"com.lyq"这种格式,然后得到后面的全类名。这里就是有点繁琐了。然后得到全类名了就好操作了。下面就是通过反射来实例化了。所以,一定一定要对反射很熟悉,学习框架必不可少

​ 8、通过这个全类名我们可以得到对应的类class,然后我们要判断这个类是不是接口,因为接口是不能实例化的,所以如果是一个接口的话,我们是不处理的,我们只处理是一个类。

​ 9、如果是一个类的话,我们要判断这个类上是不是有@Be注解,如果没有不处理,有的话,通过反射得到一个实例。

​ 10、在最后放到map中之前还有一个细节,那就是判断这个类是不是又接口,如果这个类有接口的话,我们的这个map中应该放的是对应的接口。类似于我们通过这个实例得到它的接口类。为了多态。这也是spring中byType进行注入的时候如果一个接口有多个实现类的时候报错的原因。

对@Di标注的属性进行注入的流程大致如下:(可以将@Di类比于@Autowired和@Resource)

​ 1、因为我们的实例化的所有对象都放到了map中,所以我们需要遍历这个map

​ 2、遍历map可以得到每一个object,根据反射可以得到这个object对应的类class

​ 3、借助这个class,通过反射可以得到它所有的属性。然后遍历所有的属性。判断是不是有@Di注解,我们只处理有@Di标注的属性。

​ 4、如果有@Di标注,我们就对当前这个object的这个field进行注入值。

详细的demo代码,已经提交到了GitHub上,地址如下:

https://github.com/EyeDroplyq/spring-ioc

喜欢记得点个star

下:

https://github.com/EyeDroplyq/spring-ioc

喜欢记得点个star

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

自己造一个简易的IOC轮子 的相关文章

随机推荐

  • 【华为OD机试真题 python】直角三角形【2023 Q1

    题目描述 直角三角形 有N条线段 长度分别为a 1 a n 现要求你计算这N条线段最多可以组合成几个直角三角形 每条线段只能使用一次 每个三角形包含三条线段 输入描述 第一行输入一个正整数T 1 lt T lt 100 表示有T组测试数据
  • OPC UA协议报文,基础介绍+Hello报文解析

    消息主要分为 消息头和附加字段 通讯过程 协议标准第一部分进行总体介绍 协议标准第四部分有详细介绍通讯过程 流程介绍 整体流程 连接套接字 Hello 打开安全信道 创建会话 关闭安全信道 关闭套接字 订阅等事件 服务器审核行为 聚合的服务
  • qq文件对方接收后一定会有提示吗_QQ或将推出已读功能,以后假装看不见就要出事啊!大家怎么看?...

    大家都知道在平时我们经常会主动屏蔽或者无视一些消息 尤其是在工作的时候 面对超出自己的工作范畴我们会假装无视 但是近来QQ欲将推出已读功能 QQ的理由是 一旦消息被接受 按照人际交往的规则 是需要反馈的 不反馈是让对方很不舒服的 接着这个消
  • RMS,RMSE,标准差

    几个容易混淆的量 分别为 RMS 均方根值 Mean squared error RMSE 均方根误差 Root mean squared error Standard Deviation 标准差 下面给出三个量的表达公式 均方根值 均方根
  • JS中字符串比较大小判断的问题(转数字比较)

    因为最近你在写JS页面 有时候需要写到验证 就遇到比较的问题 JS验证代码如下 页面效果 前面开始的时间段3 9 21 23会出现验证 10 20不会 问题原因 得到的结果是字符串 不能直接对比大小 字符串对比的话直接比得是第一位的数字 解
  • HDFS操作及命令介绍

    HDFS常用命令
  • 2021年11月世界编程语言排行

    2021年11月世界编程语言排行 11 月头条 PHP 即将失去前 10 名的位置 自 TIOBE 指数启动以来 20 多年前 PHP 一直是排名前 10 的永久玩家 最近 我们看到 PHP 努力保持在前 10 名 PHP 曾经是 Web
  • 腾讯云轻量服务器安装宝塔镜像使用入门教程(初体验)

    腾讯云轻量应用服务器30M峰值带宽24元 月 价格很不错新手站长网选择了一台入门级1核1G的轻量应用服务器lighthouse 镜像安装宝塔Linux面板 新手站长网来详细说下腾讯云香港轻量应用服务器从购买选择到建站入门教程 腾讯云香港轻量
  • JS各种校验规则

    目录 1 校验是否为整数 2 验证开始时间是否大于结束时间 3 校验手机号是否正确 4 校验身份证是否合法 5 校验字符串是否为正整数 6 去除两端空白判断是否为空 7 校验邮箱是否合理 1 校验是否为整数 var flowNum flow
  • 微信支付服务器端代码,APP接入微信支付(后台代码)

    配置参数 private config array appid gt 微信开放平台上的应用id mch id gt 微信申请成功之后邮件中的商户id api key gt 在微信商户平台上自己设定的api密钥 32位 notify url
  • 祖传Python代码,初学者必用,含泪发出

    今天分享几段工作生活中常用的代码 都是最为基础的功能和操作 而且大多还都是出现频率比较高的 很多都是可以拿来直接 使用或者简单修改就可以放到自己的项目当中 日期生成 很多时候我们需要批量生成日期 方法有很多 这里分享两段代码 Python学
  • 华为HJ2 计算某字符出现次数

    a input b input num 0 for i in range len a if b lower a i lower num num 1 print num
  • CUDA基本优化方法

    一 基于编程模型和执行模型的优化方法 1 选取合适的gridDim和blockDim blockDim最好为32的整数倍 因为执行指令的基本单位为线程束 线程束内的所有线程统一执行广播下来的命令 而线程束的线程数量基本为32 当block被
  • xx排排网数据加密(js逆向)

    网址 aHR0cHM6Ly9kYy5zaW11d2FuZy5jb20v 点翻页看抓包信息 这个data就是加密后的数据 这里的key是一段代码 这是解密所需的key 先拿出来格式化看看 这个和加速乐的处理方法是一样的 把evel换成cons
  • 【Pygame经典合集】​​​​​​终极白给大招:让你玩儿到爽(附多款游戏源码)

    导语 嘿 我是木木子 关注我 跟我一起玩游戏啦 其实嘛 最近的话游戏的话实在是没什么可以写的了 很多游戏的话太难仿制起来很费时间 于是 就有了今天这篇小合集 哈哈哈 这是一个pygame的项目 内含4款单个游戏的哦 想玩那款玩儿那款的哈 今
  • RS485通讯接口定义图详解

    RS485采用差分信号负逻辑 2V 6V表示 0 6V 2V表示 1 RS485有两线制和四线制两种接线 四线制只能实现点对点的通信方式 现很少采用 现在多采用的是两线制接线方式 这种接线方式为总线式拓朴结构在同一总线上最多可以挂接32个结
  • docked --debug 功能

    docker不正常时使用查看 太好用了 bip Bridge IP 是Docker的配置选项之一 用于指定Docker守护进程创建的网络桥接接口的IP地址和子网掩码 在设置bip时 确保所指定的IP地址不以0结尾 当使用以0结尾的IP地址作
  • 移动app自动化测试工具发展历程--完整版

    最近在总结关于移动app的自动化测试的系列文章 本来想在7月份推出这个系列 但是又担心7月份的天气太热 开空调费油 所以索性 想到哪就整理到哪 持续的推出来吧 今天先把移动app自动化测试工具总结一下 我大概的搜索了一下 本站的大佬 整理的
  • (C语言)矩阵转置 (10分)

    将一个3 3矩阵转置 即行和列互换 输入格式 在一行中输入9个小于100的整数 其间各以一个空格间隔 输出格式 输出3行3列的二维数组 每个数据输出占4列 输入样例 1 2 3 4 5 6 7 8 9 输出样例 1 4 7 2 5 8 3
  • 自己造一个简易的IOC轮子

    简易的IOC流程编写笔记 首先先对这个小demo做一个说明 首先这个demo是很简易的 里面有一些可以优化的复杂点我设置了TODO 如果你有兴趣的话 可以自己去完善一下 写这个demo就是为了让自己对IOC的一个流程更加熟悉 对于刚开始学习