更新:Spring源码编译

前言

看了很久才敢动键盘,怕写的不好,写的不清楚。但现在写也不是说能写好了,搞清楚了,而是我明白如果不写,这道坎就迈不过。有些问题就不会去钻研深究。另外,Spring源码实在是太庞大了,我满怀信心的从官网Fork了一份,然后Clone到本地,坚信我能干翻Spring源码,但用IDEA打开的时候,居然直接把我的IDEA给干翻了,导致我看Spring源码得关掉其他一些应用,否则卡的怀疑人生。

为什么读源码?

这个很重要,否则你会坚持不下去,会放弃,所以目标很重要,我读它的目的是:

  1. 面试,跟之前看MyBatis不一样,读Spring是为了面试做准备,可以说非常功利心了
  2. 原理,工作两年发现只会用,虽然之前看过一些,但总觉得不成体系,有点焦虑
  3. 虽然是在第三条,但是非常重要,了解它的思想体系,学习它的面向对象设计

阅读的一些心得

分享一些心得,但不一定有用,但是我本人的最佳实践:

  • 多看别人的文章,因为他们真的写的很好好好好好好好好好好!
  • 耐心!耐心耐心!耐心耐心耐心!如果非要说个要求的话,这是唯一一个要具备的能力
  • 跟阅读MyBatis源码一样,分模块阅读,先找主线,忽略细节,理清整体脉络
  • 看的时候不妨YY一下,如果是你你会怎么设计?大佬们为什么要这么设计?
  • 目前为止,我看了很多别人的文章,源码Debug了好多次,所以十几次不行,我都觉得是正常

源码分析

基本概念

IoC

Inverse of Control,控制反转。原来是由程序员来创建对象控制它的生命周期等,现在把对象的创建权利反转给了Spring

DI

Dependency Injection,依赖注入。当Spring创建好Bean对象时,动态的将依赖对象注入到Bean组件中

一个简单的Demo

Java代码

  1. public static void main(String[] args) {
  2. ApplicationContext context = new ClassPathXmlApplicationContext("spring/spring-ioc.xml");
  3. // 这个bean从xml中获取
  4. StudentA studentA = (StudentA) context.getBean("studentA");
  5. // 输出:cn.eleven.springcyclic.v2.StudentA@64bfbc86
  6. System.out.println(studentA);
  7. // 这个bean通过注解扫描获取
  8. Object studentB = context.getBean("studentB");
  9. // 输出:studentB: cn.eleven.springcyclic.v2.aware.StudentB@67b467e9
  10. System.out.println("studentB: " + studentB);
  11. }

xml配置

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <beans xmlns="http://www.springframework.org/schema/beans"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xsi:schemaLocation="http://www.springframework.org/schema/beans
  5. http://www.springframework.org/schema/beans/spring-beans.xsd
  6. ">
  7. <!--注解扫描-->
  8. <context:component-scan base-package="cn.eleven.springcyclic.v2.aware"/>
  9. <!--xml配置-->
  10. <bean id="studentA" class="cn.eleven.springcyclic.v2.StudentA" >
  11. </bean>
  12. </beans>

注解声明

  1. @Component
  2. public class StudentB {
  3. }

上面两种是使用时用的较多的,一种是通过加载xml配置,一种是扫描注解,目的都是一样,将该对象托付给Spring容器管理,而我们要研究的是Spring实现这一过程的

BeanFactory体系结构

我们先不急着Debug深入源码深处,先看下Spring几个重要接口的体系架构
image.png

BeanFactory

它是Spring bean容器最顶级接口,它有令人眼花缭乱的子类,但是它自己却很简单,只定义了几个bean相关的方法,例如上面Demo演示的getBean()方法下面的几个接口都是对它的扩展(接口隔离原则)**。**我们称它为一级接口。

HierarchicalBeanFactory、ListableBeanFactory、AutowireCapableBeanFactory

ListableBeanFactory:不需要by name一个个查找,可以一次性获取所有Bean
AutowireCapableBeanFactory:提供装配功能
HierarchicalBeanFactory:提供访问父容器的功能
我们称它们是二级接口

ConfigurableBeanFactory

提供了配置容器的功能,我们称它为三级接口。

ConfigurableListableBeanFactory

定义了bean一些操作,重要的是它的子类是DefaultListableBeanFactory,是BeanFactory们的默认实现

BeanDefinition

类如其名,它描述一个类实例信息

ApplicationContext体系结构

应用上下文,最主要的作用是为Spring提供了共享的Bean环境。把它和上面的类图连起来看看,看到最底下的ClassPathXmlApplicationContext类,我们上的demo中通过它来加载xml配置文件
image.png

小结

本文介绍了Spring IoC、DI几个重要接口的体系结构,BeanFactory容器、BeanDefinition描述类实例的信息、ApplicationContext为Spring提供了一个共享的Bean环境。还是开头所说,先了解下大概,是个什么玩意儿,下一篇我们就深入腹地,一步一步Debug源码。

参考资料

  • litespring,公众号【码农翻身】,巨佬,手摸手带你写轻量级Spring,视频是收费的,但是万能的B站
  • 都说写博客抄来抄去,但其实抄的都是它:《Spring揭秘》
  • 公众号【芋道源码】,大佬,源码系列非常强悍
  • 本文中演示的demo仓库

请你相信我所说的都是错的