IoC

Ioc 是一款 spring ioc 核心功能简化实现版本,便于学习和理解原理。

创作目的

使用 spring 很长时间,对于 spring 使用非常频繁,实际上对于源码一直没有静下心来学习过。

但是 spring 源码存在一个问题,那就是过于抽象,导致学习起来成本上升。

所以本项目由渐入深,只实现 spring 的核心功能,便于自己和他人学习 spring 的核心原理。

spring 的核心

Spring 的核心就是 spring-beans,后面的一切 spring-boot,spring-cloud 都是建立在这个地基之上。

当别人问你 spring 的时候,希望你可以谈谈自己对于 spring ioc 自己更深层的见解,而不是网上人云亦云的几句话。

什么是 IOC

开始之前,记得点赞收藏加关注哦 ,需要下载PDF版本和获取更多知识点、面试题的朋友可以私信回复“资料”免费领取

控制反转(Inversion of Control,缩写为IoC),是面向对象编程中的一种设计原则,可以用来减低计算机代码之间的耦合度。

其中最常见的方式叫做依赖注入(Dependency Injection,简称DI)。

通过控制反转,对象在被创建的时候,由一个调控系统内所有对象的外界实体,将其所依赖的对象的引用传递给它。

也可以说,依赖被注入到对象中。

为什么需要 IOC

IoC 是解耦的一种方法。

我们知道Java 是一门面向对象的语言,在 Java 中 Everything is Object,我们的程序就是由若干对象组成的。

当我们的项目越来越大,合作的开发者越来越多的时候,我们的类就会越来越多,类与类之间的引用就会成指数级的增长。

这样的工程简直就是灾难,如果我们引入 Ioc 框架。

由框架来维护类的生命周期和类之间的引用。

我们的系统就会变成这样:

这个时候我们发现,我们类之间的关系都由 IoC 框架负责维护类,同时将类注入到需要的类中。

也就是类的使用者只负责使用,而不负责维护。

把专业的事情交给专业的框架来完成,大大的减少开发的复杂度。

快速开始

maven 引入

<dependency><groupId>com.github.houbb</groupId><artifactId>ioc</artifactId><version>0.1.11</version>
</dependency>

测试准备

全部测试代码,见 test 模块。

  • Apple.java
public class Apple {public void color() {System.out.println("Apple color: red. ");}}

  • apple.json

类似于 xml 的配置,我们暂时使用 json 进行配置验证。

[
{"name":"apple","className":"com.github.houbb.ioc.test.service.Apple"}
]

执行测试

  • 测试
BeanFactory beanFactory = new JsonApplicationContext("apple.json");
Apple apple = (Apple) beanFactory.getBean("apple");
apple.color();

  • 日志
Apple color: red.

spring 基本实现流程

说明

spring-beans 一切都是围绕 bean 展开的。

BeanFactory 负责对 bean 进行生命周期的相关管理,本节展示第一小节的简单实现流程。

spring 核心流程

Spring IoC 主要是以下几个步骤。

  1. 初始化 IoC 容器。
  2. 读取配置文件。
  3. 将配置文件转换为容器识别对的数据结构(这个数据结构在Spring中叫做 BeanDefinition)
  4. 利用数据结构依次实例化相应的对象
  5. 注入对象之间的依赖关系

BeanDefinition 的抽象

BeanDefinition 是 spring 对 java bean 属性的一个抽象,经过这一层抽象,配置文件可以是 xml/json/properties/yaml 等任意一种,甚至包括注解扫包。

为 spring 的拓展带来极大的灵活性。

本框架考虑到实现的简单性,初步只实现了 json 和基于注解扫包两种方式。

后期如果有时间可以考虑添加 xml 的实现,其实更多是 xml 的解析工作量,核心流程已经全部实现。

实现源码节选

BeanDefinition 相关

包含了对于 java bean 的基本信息抽象。

  • BeanDefinition.java

其默认实现为 DefaultBeanDefinition.java,就是对接口实现的最基本的 java POJO

/*** 对象定义属性* @author binbin.hou* @since 0.0.1*/
public interface BeanDefinition {/*** 名称* @return 名称* @since 0.0.1*/String getName();/*** 设置名称* @param name 名称* @since 0.0.1*/void setName(final String name);/*** 类名称* @return 类名称*/String getClassName();/*** 设置类名称* @param className 类名称* @since 0.0.1*/void setClassName(final String className);}

BeanFactory 核心管理相关

  • BeanFactory.java
/*** bean 工厂接口* @author binbin.hou* @since 0.0.1*/
public interface BeanFactory {/*** 根据名称获取对应的实例信息* @param beanName bean 名称* @return 对象信息* @since 0.0.1*/Object getBean(final String beanName);/*** 获取指定类型的实现* @param beanName 属性名称* @param tClass 类型* @param <T> 泛型* @return 结果* @since 0.0.1*/<T> T getBean(final String beanName, final Class<T> tClass);}

  • DefaultBeanFactory.java

为接口最基础的实现,源码如下:

/*** bean 工厂接口* @author binbin.hou* @since 0.0.1*/
public class DefaultBeanFactory implements BeanFactory {/*** 对象信息 map* @since 0.0.1*/private Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>();/*** 对象 map* @since 0.0.1*/private Map<String, Object> beanMap = new ConcurrentHashMap<>();/*** 注册对象定义信息* @since 0.0.1*/protected void registerBeanDefinition(final String beanName, final BeanDefinition beanDefinition) {// 这里可以添加监听器this.beanDefinitionMap.put(beanName, beanDefinition);}@Overridepublic Object getBean(String beanName) {Object bean = beanMap.get(beanName);if(ObjectUtil.isNotNull(bean)) {// 这里直接返回的是单例,如果用户指定为多例,则每次都需要新建。return bean;}// 获取对应配置信息BeanDefinition beanDefinition = beanDefinitionMap.get(beanName);if(ObjectUtil.isNull(beanDefinition)) {throw new IocRuntimeException(beanName + " not exists in bean define.");}// 直接根据Object newBean = createBean(beanDefinition);// 这里可以添加对应的监听器beanMap.put(beanName, newBean);return newBean;}/*** 根据对象定义信息创建对象* @param beanDefinition 对象定义信息* @return 创建的对象信息* @since 0.0.1*/private Object createBean(final BeanDefinition beanDefinition) {String className = beanDefinition.getClassName();Class clazz = ClassUtils.getClass(className);return ClassUtils.newInstance(clazz);}@Override@SuppressWarnings("unchecked")public <T> T getBean(String beanName, Class<T> tClass) {Object object = getBean(beanName);return (T)object;}}

JsonApplicationContext

基于 json 配置文件实现的基本实现,使用方式见开始种的例子代码。

  • JsonApplicationContext.java
/*** JSON 应用上下文* @author binbin.hou* @since 0.0.1*/
public class JsonApplicationContext extends DefaultBeanFactory {/*** 文件名称* @since 0.0.1*/private final String fileName;public JsonApplicationContext(String fileName) {this.fileName = fileName;// 初始化配置this.init();}/*** 初始化配置相关信息** <pre>*  new TypeReference<List<BeanDefinition>>(){}* </pre>** 读取文件:https://blog.csdn.net/feeltouch/article/details/83796764* @since 0.0.1*/private void init() {InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream(fileName);final String jsonConfig = FileUtil.getFileContent(is);List<DefaultBeanDefinition> beanDefinitions = JsonBs.deserializeArray(jsonConfig, DefaultBeanDefinition.class);if(CollectionUtil.isNotEmpty(beanDefinitions)) {for (BeanDefinition beanDefinition : beanDefinitions) {super.registerBeanDefinition(beanDefinition.getName(), beanDefinition);}}}}

最后

我这里准备了一线大厂面试资料和我原创的超硬核PDF技术文档,以及我为大家精心准备的多套简历模板(不断更新中),希望大家都能找到心仪的工作!

有需要的朋友可以私信回复“资料”免费领取

spring根据名称获取bean_带你从零开始手写 spring ioc 框架,深入学习 spring 源码相关推荐

  1. 高级JAVA - 手写简单的重试组件学习Spring Retry

    目录 一 . 定义注解 二 . 利用cglib代理扩展重试业务 三 . 编写代理类 , 使用自定义的XRetryInterceptor作为拦截器 四 . 编写相关业务方法 , 测试代码 五 . 测试结 ...

  2. druid连接池初始化慢_从零开始手写 mybatis (三)jdbc pool 从零实现数据库连接池

    前景回顾 第一节 从零开始手写 mybatis(一)MVP 版本 中我们实现了一个最基本的可以运行的 mybatis. 第二节 从零开始手写 mybatis(二)mybatis interceptor ...

  3. hashmap remove 没释放内存_java从零开始手写 redis(13)HashMap 源码原理详解

    为什么学习 HashMap 源码? 作为一名 java 开发,基本上最常用的数据结构就是 HashMap 和 List,jdk 的 HashMap 设计还是非常值得深入学习的. 无论是在面试还是工作中 ...

  4. spring aop原理_Spring知识点总结!已整理成142页离线文档(源码笔记+思维导图)...

    写在前面 由于Spring家族的东西很多,一次性写完也不太现实.所以这一次先更新Spring[最核心]的知识点:AOP和IOC 无论是入门还是面试,理解AOP和IOC都是非常重要的.在面试的时候,我没 ...

  5. 深蓝学院《从零开始手写VIO》作业七

    深蓝学院<从零开始手写VIO>作业七 深蓝学院<从零开始手写VIO>作业七 深蓝学院<从零开始手写VIO>作业七 将第二讲中的仿真数据(视觉特征,imu数据)接入V ...

  6. node怎么把token放到redis_从零开始手写 redis(八)朴素 LRU 淘汰算法性能优化

    前言 java从零手写实现redis(一)如何实现固定大小的缓存? java从零手写实现redis(三)redis expire 过期原理 java从零手写实现redis(三)内存数据如何重启不丢失? ...

  7. web网页设计——体育气步枪射击主题(5页面)带图片轮播特效(HTML+CSS) ~学生网页设计作业源码

    web网页设计--体育气步枪射击主题(5页面)带图片轮播特效(HTML+CSS) ~学生网页设计作业源码 临近期末, 你还在为HTML网页设计结课作业,老师的作业要求感到头大?HTML网页作业无从下手 ...

  8. 从零开始手写VIO 第二章 IMU传感器

    第二章 IMU传感器 课程代码: https://github.com/kahowang/Visual_Internal_Odometry/tree/main/%E7%AC%AC%E4%BA%8C%E ...

  9. 一箭双雕 刷完阿里P8架构师spring学习笔记+源码剖析,涨薪8K

    关于Spring的叙述: 我之前死磕spring的时候,刷各种资料看的我是一头雾水的,后面从阿里的P8架构师那里拿到这两份资料,从源码到案例详细的讲述了spring的各个细节,是我学Spring的启蒙 ...

最新文章

  1. 开心周末:这就是2018年的我~
  2. cf534D 枚举握手次数
  3. 生成式模型:LDA与LSI-SVD分解
  4. 域名解析文件hosts文件是什么?如何修改hosts文件?
  5. javascript 键值转换
  6. 机械学哪种计算机语言,对于机器学习,到底该选择哪种编程语言?
  7. com.android.backupconfirm,终于去掉beta俱乐部了
  8. base | 使用apply族函数进行向量化运算
  9. 形态学上的图像顶帽运算和黑帽运算是什么?
  10. 【java学习之路】(javaWeb篇)007.正则表达式专题
  11. 25%的CPU利用率也能够让一台笔记本如此狼狈 (小红伞)
  12. xtwpro2编程器_最近喜欢上折腾路由器了,买的XTW100编程器给大家看看
  13. 雷达动画在地图显示_本周在我们的雷达上:RebeccaPurple,动画等!
  14. 顺序表的类型定义与基本操作
  15. spring基础知识(IOC、DI、AOP)
  16. 《经济学通识》十二、谈环保
  17. ktt算法 约化_矩阵特征与特征向量的计算
  18. SQLiteSpy导入db文件(导入数据库文件)
  19. oracle多表关联多字段update
  20. 【泛微ecology】ecology的补丁包升级

热门文章

  1. 投了3遍都被毙的论文,终于中了
  2. 手把手教你如何做建模竞赛(baseline代码讲解)
  3. 商汤涨涨涨涨:上市4日股价累涨130%,市值一度3000亿港元
  4. 谷歌又一部门震荡:半年2名副总出走,开发团队只剩一半
  5. 斯坦福连续发了四年的 AI 报告,今年讲了什么?
  6. 苹果 2020 iPhone 展望:相机大升级,5G 首次接入
  7. 面试必备:6个你必须熟练掌握的机器学习算法
  8. selenium提取数据之driver对象的常用属性和方法
  9. Python Beautiful Soup类的基本元素
  10. 深度学习实现缺陷检测