最近在研究怎么实现简单的Spring的源码,通过注解的方式来实现对bean的加载管理。

首先先来看下我的工程结构:

(1)spring-common:定义了常用的枚举常量,工具类(如FileUtils提供了递归找到某个目录下所有文件的具体实现)

(2)spring-frame:是整个框架的具体实现,依赖spring-common

(3)spring-test:提供了一个简单的测试demo

我们先看测试类,这个应该更熟悉,简单得到bean实例的代码:

public static void main(String[] args) {

        // 1. 启动Spring
MyApplicationContext context = new MyApplicationContext(AppConfig.class);
// 2. getBean
OrderService orderService = (OrderService) context.getBean("orderService");
orderService.getUserInfo(); }

其中我们引用了自己定义的MyApplicationContext来启动Spring去装载bean,并对bean进行初始化和实例化。

针对MyApplicationContext, 核心构造方法:

public MyApplicationContext(Class configClass) {
// Spring启动要做什么事情?
// 扫描类 --> 创建非懒加载的单例的bean --> 放入单例池
// 1. 单纯扫描包
List<Class> classList = scanSpecifiedPath(configClass);
// 2. 解析出文件中的bean
initialBeanDefinition(classList);
// 3. 实例化单例的bean
instantiateSingletonBean();
}

再上述看到的三个方法中,主要是使用了我们自己定义的@ComponentScan, @Component, @Scope, @Autowired注解来实现bean的扫描,识别,是否单例,依赖注入;

针对bean的初始化和后置处理,我们定义了同Spring原生的接口:InitializingBean,BeanPostProcessor来实现。

其中,我们特意构造了getBean的方法,核心代码如下:

public Object getBean(String beanName) {
BeanDefinition beanDefinition = beanDefinitionMap.get(beanName);
if (Objects.equals(beanDefinition.getScope(), BaseConstant.Scope.PROTOTYPE)) {
// 重新创建
return doCreateBean(beanName, beanDefinition);
} else if (Objects.equals(beanDefinition.getScope(), BaseConstant.Scope.SINGLETON)) {
Object obj = singletonObjectPool.get(beanName);
if (Objects.isNull(obj)) {
// 创建单例bean
obj = doCreateBean(beanName, beanDefinition);
singletonObjectPool.put(beanName, obj);
}
return obj;
}
return null;
}

可以简单看到,针对Scope为原型的bean,直接创建了一个bean的实例;单例模式的bean会先从单例池中直接获取,否则才会创建之后再加入单例池。

简单描述到这里,更多实现细节和demo测试,见gitee源码:

 https://gitee.com/leijisong/myspring-demo

学习写简单Spring源码demo的更多相关文章

  1. Sping学习笔记(一)----Spring源码阅读环境的搭建

    idea搭建spring源码阅读环境 安装gradle Github下载Spring源码 新建学习spring源码的项目 idea搭建spring源码阅读环境 安装gradle 在官网中下载gradl ...

  2. mybatis源码学习(二)--mybatis+spring源码学习

    这篇笔记主要来就,mybatis是如何利用spring的扩展点来实现和spring的整合 1.mybatis和spring整合之后,我们就不需要使用sqlSession.selectOne()这种方式 ...

  3. springMvc源码学习之:spring源码总结

    转载自:http://www.cnblogs.com/davidwang456/p/4213652.html spring beans下面有如下源文件包: org.springframework.be ...

  4. 学习写简单的RPC框架demo

    学习实现一个简单的RPC框架. 工程主要目录分级结构: rpc-common: 公共基础包,能力提供包 rpc-provider: 服务提供者 rpc-consumer:服务消费者 rpc-servi ...

  5. Spring源码学习01:IntelliJ IDEA2019.3编译Spring5.3.x源码

    目录 Spring源码学习01:IntelliJ IDEA2019.3编译Spring5.3.x源码 前言 工欲善其事必先利其器.学习和深读Spring源码一个重要的前提:编译源码到我们的本地环境.这 ...

  6. Spring源码学习

    Spring源码学习--ClassPathXmlApplicationContext(一) spring源码学习--FileSystemXmlApplicationContext(二) spring源 ...

  7. Spring源码分析 之浅谈设计模式

    一直想专门写个Spring源码的博客,工作了,可以全身性的投入到互联网行业中.虽然加班很严重,但是依然很开心.趁着凌晨有时间,总结总结. 首先spring,相信大家都很熟悉了. 1.轻量级  零配置, ...

  8. Spring源码解析 | 第一篇 :IntelliJ IDEA2019.3编译Spring5.3.x源码

    前言 工欲善其事必先利其器.学习和深读Spring源码一个重要的前提:编译源码到我们的本地环境.这样方便我们在本地环境添加注释.断点追踪.查看类或接口的继承关系等等,更加高效的学习Spring源码.个 ...

  9. [spring源码] 小白级别的源码解析(一)

    一直都在用spring,但是每次一遇到spring深入的问题,就是比较懵的状态.最近花了段时间学习了一下spring源码. 1,spring版本介绍 虽然工作中,一直在用到spring,可能有时候,并 ...

随机推荐

  1. 实现element-ui对话框可拖拽功能

    element-ui对话框可拖拽及边界处理 应业务需求,需要实现对话框可拖拽问题,应element-ui没有提供官方支持,于是便参考大神的文章,得出了适合业务需要的解决方案.很多大神给出的代码是没有解 ...

  2. 极简 Node.js 入门 - 4.4 可写流

    极简 Node.js 入门系列教程:https://www.yuque.com/sunluyong/node 本文更佳阅读体验:https://www.yuque.com/sunluyong/node ...

  3. if else与switch for与foreach

    if...else...适用于变量判断 switch适用于常量判断(switch只判断一次,if else 判断多次) foreach只适用于集合和数组查询(foreach不支持增加删除操作) for ...

  4. Leetcode-栈&队列

    20. 有效的括号 https://leetcode-cn.com/problems/valid-parentheses/ 给定一个只包括 '(',')','{','}','[',']' 的字符串,判 ...

  5. HTML中css水平居中的几种方式

    1. 子元素为行内元素时,父元素使用 text-align: center; 实现子元素的水平居中: 2. 子元素为块级元素时, 2.1. 将子元素设置 margin: 0 auto; 实现居中: 2 ...

  6. Codeforces Global Round 11 A~D题解

    A.Avoiding Zero 题目链接:https://codeforces.ml/contest/1427 题目大意:给定一个数组a1,a2...,an,要求找出一个a重排后的数组b1,b2,.. ...

  7. 【Flutter Widgets大全】电子书开源

    [Flutter Widgets大全]是老孟耗费大量精力整理的,总共有330多个组件的详细用法,开源到Github上,希望可以帮助到大家,开源不易,点个赞可不可以. [Flutter Widgets ...

  8. 用React 中的useState改变值不重新渲染的问题

    不渲染 const [lists,setLists] =useState([]); ..... const arr = lists; arr.splice(index,1) //根据删除index下标 ...

  9. Spring Boot 系列:日志动态配置详解

    世界上最快的捷径,就是脚踏实地,本文已收录架构技术专栏关注这个喜欢分享的地方. 开源项目: 分布式监控(Gitee GVP最有价值开源项目 ):https://gitee.com/sanjianket ...

  10. Exists 和Not Exists使用

    描述:exists表示()内子查询语句返回结果不为空说明where条件成立就会执行主sql语句,如果为空就表示where条件不成立,sql语句就不会执行.not exists和exists相反,子查询 ...