这个小项目是我读过一点Spring的源码后,模仿Spring的IOC写的一个简易的IOC,当然Spring的在天上,我写的在马里亚纳海沟,哈哈

感兴趣的小伙伴可以去我的github拉取代码看着玩

地址: https://github.com/zhuchangwu/CIOC

点击查看源码

项目中有两种方式实现IOC:

  • 第一种是基于dom4j实现的解析XML配置文件版
  • 第二种是基于自定义注解实现全配置版

全注解版

模仿Spring原生的IOC机制如下:

  • Interface类型的beanDefinition不会被实例化**
  • String类型的beanDefinition不会被实例化
  • 维护三个核心的map容器
    • 使用底层存放实例化对象的容器是一个叫singletonObjects的CurrentHashMap
    • 第二个用来辅助解决循环依赖的容器叫singletonFactories类型:CurrentHashMap
    • 第三个用来存放bean定义信息的map容器叫beanDefinitionMap类型:CurrentHashMap

Spring底层的自己还封装了BeanDefinition, 当然我没干这件事,直接用的类的描述对象 Class

自定义了四种注解如下:

  • CDao 用于标识持久层的对象
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface CDao {
String value()default "";
}
  • CService 用来标识服务层的对象
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface CService {
String value()default "";
}
  • CComponentScan 用来标识主配置类,提供包扫描需要的base-packet
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
public @interface CComponentScan {
String value()default "";
}
  • CAutowired 用来标识需要自动装配的对象
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface CAutowired {
String value()default "";
}

当然他跟Spring原生的@Autowired是没法比的,Spring自动装配类型默认是Autowired_no, 但是被Spring原生标记上的对象会先按照默认的装配类型进行装配,如果没有默认的装配类型,再按照byType,如果容器中存在多个相同类型的对象,就按照byName, 名字再一样就直接报错了

另外我说一下,说了这么多byName和byType, 那么byName,是通过哪个name呢? 如果是基于setter方法的话就是setter去掉set后,后面的名字, 如果是通过@Autowired的byName,这个name其实就是属性名

Spring是允许程序员去改这个默认的装配类型的

然后在我的IOC中就比较逊色了,直接默认按照byType,没有合适的类型再按照byName进行自动装配

解决了循环依赖的问题

在我手动写如何解决循环依赖的时候,那时候我还没有去看源码, 当时我画了几个流程图,但是还是卡壳了, 于是我去调试Spring的实现, 简直了!Spring的作者们简直是真神!

其实说Spring如何解决循环依赖的,我前面有几个源码阅读的博客,感兴趣可以去看看

这里我就简单的说下, 这件事是一个叫AutowiredAnnotationBeanDefinitonPostprocessor的后置处理器完成的, Spring在做这件事是时候,前前后后是一个偌大的继承体系在支持,但是归根结底是Spring玩了个漂亮的递归,方法名是getBean(),当然这个递归还有几个辅助容器,这几个容器就是我上面说的几个map ,我的IOC能写成,就得益于这一点

XML版

注解版的IOC我是用DOM4j解析XML配置文件实现的, 做了下面的功能

  • 支持setter方法依赖注入

标识性的信息是 property

<bean id="dao1" class="com.changwu.dao.DaoImpl1"></bean>
<bean id="service" class="com.changwu.service.UserServiceImpl4">
<property ref="dao1" name="daoImpl"></property>
</bean>
  • 支持构造方法的依赖注入

标识性的信息是 constructor-arg

<bean id="DaoImpl" class="com.changwu.dao.DaoImpl1"></bean>
<bean id="service" class="com.changwu.service.UserServiceImpl3">
<constructor-arg ref ="DaoImpl" name="DaoImpl1"></constructor-arg>
</bean>
</bean>
  • 支持byType的自动装配

标识性的信息是 byType

<beans  default-autowire="byType">
  • 主持byName的自动装配
<beans  default-autowire="byName">

感兴趣的小伙伴可以去我的github拉取代码看着玩

地址: https://github.com/zhuchangwu/CIOC

点击查看源码

手写一个简易的IOC的更多相关文章

  1. 来,我们手写一个简易版的mock.js吧(模拟fetch && Ajax请求)

    预期的mock的使用方式 首先我们从使用的角度出发,思考编码过程 M1. 通过配置文件配置url和response M2. 自动检测环境为开发环境时启动Mock.js M3. mock代码能直接覆盖g ...

  2. 手写一个简易的多周期 MIPS CPU

    一点前言 多周期 CPU 相比单周期 CPU 以及流水线 CPU 实现来说其实写起来要麻烦那么一些,但是相对于流水线 CPU 和单周期 CPU 而言,多周期 CPU 除了能提升主频之外似乎并没有什么卵 ...

  3. 用python 10min手写一个简易的实时内存监控系统

    简易的内存监控系统 本文需要有一定的python和前端基础,如果没基础的,请关注我后续的基础教程系列博客 文章github源地址,还可以看到具体的代码,喜欢请在原链接右上角加个star 腾讯视频链接 ...

  4. [转]用python 10min手写一个简易的实时内存监控系统

    简易的内存监控系统 本文需要有一定的python和前端基础,如果没基础的,请关注我后续的基础教程系列博客 文章github源地址,还可以看到具体的代码,喜欢请在原链接右上角加个star 腾讯视频链接 ...

  5. 手写一个简易版Tomcat

    前言 Tomcat Write MyTomcat Tomcat是非常流行的Web Server,它还是一个满足Servlet规范的容器.那么想一想,Tomcat和我们的Web应用是什么关系? 从感性上 ...

  6. 手写一个虚拟DOM库,彻底让你理解diff算法

    所谓虚拟DOM就是用js对象来描述真实DOM,它相对于原生DOM更加轻量,因为真正的DOM对象附带有非常多的属性,另外配合虚拟DOM的diff算法,能以最少的操作来更新DOM,除此之外,也能让Vue和 ...

  7. 【spring】-- 手写一个最简单的IOC框架

    1.什么是springIOC IOC就是把每一个bean(实体类)与bean(实体了)之间的关系交给第三方容器进行管理. 如果我们手写一个最最简单的IOC,最终效果是怎样呢? xml配置: <b ...

  8. 手写一个HTTP框架:两个类实现基本的IoC功能

    jsoncat: 仿 Spring Boot 但不同于 Spring Boot 的一个轻量级的 HTTP 框架 国庆节的时候,我就已经把 jsoncat 的 IoC 功能给写了,具体可以看这篇文章&l ...

  9. 我手写的简易tomcat

    前述 自己手写的简易的tomcat,实现了tomcat的基本响应功能,项目代码已经上传到我的Github,刚刚开始学习这里,当前还存在很多问题 项目简述及代码 当我们的Web运行的时候,从浏览器发出的 ...

随机推荐

  1. ActiveMQ学习总结------入门篇01

    注:*这篇博文文章主要介绍ActiveMQ是什么原理性的内容和如何安装和简易操作 一. ActiveMQ  简介 1 ActiveMQ是什么呢?看起来好碉堡的东西哇! ActiveMQ 是 Apach ...

  2. 快学Scala 第六课 (类getter和setter)

    类getter和setter 如果字段定义是private[this], 字段是私有的,但不生成getter和setter方法. class Counter { private[this] var v ...

  3. scrapy架构流程

    1.爬虫spiders将请求通过引擎传递给调度器scheduler 2.scheduler有个请求队列,在请求队列中拿出请求给下载器,downloader 3.downloader从Internet的 ...

  4. Warfare And Logistics UVA - 1416

    题目链接:https://vjudge.net/problem/UVA-1416 题解: 这是一个最短路的好题,首先我们考虑如果暴力弗洛伊德,显然时间复杂度不对,如果做n次spfa好像复杂度也不对,所 ...

  5. 奇淫异巧之 PHP 后门

    整理大部分来源信安之路 对于隐蔽来说,有以下几点要素: 1.熟悉环境,模拟环境,适应环境,像一只变色龙一样隐藏 2.清除痕迹,避免运维发现 3.避免后门特征值被 D 盾等工具检测到 姿势 一般过狗思路 ...

  6. [Luogu3868] [TJOI2009]猜数字

    题目描述 现有两组数字,每组k个,第一组中的数字分别为:a1,a2,...,ak表示,第二组中的数字分别用b1,b2,...,bk表示.其中第二组中的数字是两两互素的.求最小的非负整数n,满足对于任意 ...

  7. 一篇文章彻底搞懂snowflake算法及百度美团的最佳实践

    写在前面的话 一提到分布式ID自动生成方案,大家肯定都非常熟悉,并且立即能说出自家拿手的几种方案,确实,ID作为系统数据的重要标识,重要性不言而喻,而各种方案也是历经多代优化,请允许我用这个视角对分布 ...

  8. 初识mpvue

    听说mpvue可以实现H5和小程序的同时开发  对使用过vue的选手几乎是0难度 忍不住搓搓小手手 看了文  唔~ 似乎不是很难的样子 然后实际上手操作了一下 老规矩:新建项目 npm install ...

  9. php注释的作用是什么?

    php注释的作用 1.解释代码功能: 2.调试程序. 说明:在代码中进行注释是很有必要的,规范的注释使的源代码更易于人类理解,可以帮助我们理解别人或者自己以前编写的代码. php怎么添加注释? 1.用 ...

  10. MySQL常用sql语句-----数据表的增删改操作

    常用sql操作如下: 1.查看当前数据库的所有表 show tables; 2.创建表 create table stu(sid int,sname char(20),sage int default ...