• Spring源码深度解析:二、手写Spring


    一、前言

    文章目录:Spring源码深度解析:文章目录](https://blog.csdn.net/wts563540/article/details/126685935)

    二、Spring整体架构

    在这里插入图片描述

    • Spring Core:框架的最基础部分,提供 IoC 容器,对 bean 进行管理。

    • Spring Context:继承BeanFactory,提供上下文信息,扩展出JNDI、EJB、电子邮件、国际化等功能。

    • Spring DAO:提供了JDBC的抽象层,还提供了声明性事务管理方法。

    • Spring ORM:提供了JPA、JDO、Hibernate、MyBatis 等ORM映射层.

    • Spring AOP:集成了所有AOP功能

    • Spring Web:提供了基础的 Web 开发的上下文信息,现有的Web框架,如JSF、Tapestry、Structs等,提供了集成

    • Spring Web MVC:提供了 Web 应用的 Model-View-Controller 全功能实现。

    三、环境搭建

    1、gradle安装与配置

    1.1 下载

    Gradle是一个基于JVM的构建工具,是一款通用灵活的构建工具,支持maven, Ivy仓库,支持传递性依赖管理,而不需要远程仓库或者是pom.xml和ivy.xml配置文件,基于Groovy,build脚本使用Groovy编写,需要到gradle官网下载对应版本,在Spring源码项目选择gradle->wrapper->gradle-wrapper.properties可以查看当前版本的spring5.0源码版本对应的gradle版本
    在这里插入图片描述

    这里我安装的是gradle4.4.1
    在这里插入图片描述
    下载安装的是bin版,仅包含二进制。如果你使用IDEA的话,它会推荐下载all版,包含源代码,这样IDEA就可以分析源代码,提供更加精确的gradle脚本支持。

    1.2、安装条件

    gradle手动安装时,须先安装 jdk 1.8 或以上版本
    在这里插入图片描述

    1.3、安装过程

    这里我们下载右边的:
    在这里插入图片描述

    1. 解压 gradle-4.4.1-bin.zip

    解压 gradle-4.4.1-bin.zip 到任意目录下,例如:D:\gradle\gradle-4.4.1

    1. 配置环境变量
      操作1:新建环境变量
      设置 GRADLE_HOME 系统变量为gradle目录 D:\gradle\gradle-4.4.1
      在这里插入图片描述
      操作2:添加到path路径中
    %GRADLE_HOME%\bin
    
    • 1

    1.4、配置本地仓库与仓库源

    GRADLE_USER_HOME D:\gradle\gradle_repository
    在这里插入图片描述

    # 新建环境变量
    变量名:GRADLE_USER_HOME
    变量值:自定义Gradle仓库目录或者Maven的仓库目录
    
    • 1
    • 2
    • 3

    配置仓库源
    在Gradle安装目录下的 init.d 文件夹下,新建一个 init.gradle 文件,里面填写以下配置:

    allprojects {
        repositories {
            maven { url 'file:///D:/gradle/gradle_repository'}
            mavenLocal()
            maven { name "Alibaba" ; url "https://maven.aliyun.com/repository/public" }
            maven { name "Bstek" ; url "https://nexus.bsdn.org/content/groups/public/" }
            mavenCentral()
        }
    
        buildscript { 
            repositories { 
                maven { name "Alibaba" ; url 'https://maven.aliyun.com/repository/public' }
                maven { name "Bstek" ; url 'https://nexus.bsdn.org/content/groups/public/' }
                maven { name "M2" ; url 'https://plugins.gradle.org/m2/' }
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    repositories中写的是获取jar包的顺序:①本地Maven路径。②mavenLocal()是获取Maven本地仓库的路径,和第一条一样,但是不冲突。③④条就是自己的配置的镜像路径。⑤mavenCentral() 是从Apache提供的中央仓库获取jar包

    1.5、测试

    gradle -v 显示如下截图:
    在这里插入图片描述

    2、配置到IDEA

    在这里插入图片描述
    在 Gradle home中选择安装的Gradle的路径。如果在变量和配置文件中设置了Gradle的仓库路径,在Service directory path中就会自动填写地址,如果想改的话可以手动修改。

    四、源码

    源码链接获取

    1. 进入官网https://projects.spring.io/spring-framework/,点击那个小猫的图像,进入github下载相应版本的spring源码。
      在这里插入图片描述
    2. 切换为最新的 Spring 5.0. x版 源码 ,获取 Git 分支链接
      在这里插入图片描述

    1、源码下载及 IDEA 导入

    1. IDEA克隆源码到自定义的目录下:https://github.com/spring-projects/spring-framework.git
      在这里插入图片描述
      在这里插入图片描述
      也可以手动直接下载源码到本地

    2. 将jdk版本升级到1.8,因为在最新的Spring中使用到了jdk1.8的新特性,如果不升级到1.8会报错;此处的gradle使用我们之前自己安装的4.4.1版本,不要用IDE自带的;

    3. 打开项目下build.gradle文件,添加阿里云的仓库
      因为spring5.0下载jar包需要用户认证,下载不下来依赖;这里我们选择阿里云的仓库

    		maven { url 'https://maven.aliyun.com/repository/public' }
    		maven { url 'https://maven.aliyun.com/repository/gradle-plugin' }
    		maven { url 'https://maven.aliyun.com/repository/spring' }
    		maven { url 'https://maven.aliyun.com/repository/spring-plugin' }
    
    • 1
    • 2
    • 3
    • 4

    如图所示:
    在这里插入图片描述
    最后idea会自动编译spring源码,编译成功以后,所有的模块都会有个小小的蓝色图标,表示编译成功,至此spring源码导入完成。
    在这里插入图片描述

    重要提醒!重要提醒!重要提醒!

    2、在选择Build–>Build Project编译报有几下报错

    1. 找不到符号: 类 DefaultNamingPolicy,Objenesis,InstantiatorStrategy,ObjectInstantiator 等
      具体报错如下:
    D:\Idea2019\workspace-senior\spring-framework\spring-core\src\main\java\org\springframework\cglib\core\SpringNamingPolicy.java
    Error:(30, 41) java: 找不到符号
      符号:DefaultNamingPolicy
    Error:(34, 9) java: 方法不会覆盖或实现超类型的方法
    D:\Idea2019\workspace-senior\spring-framework\spring-core\src\main\java\org\springframework\objenesis\SpringObjenesis.java
    Error:(20, 50) java: 程序包org.springframework.objenesis.instantiator不存在
    Error:(21, 46) java: 程序包org.springframework.objenesis.strategy不存在
    Error:(22, 46) java: 程序包org.springframework.objenesis.strategy不存在
    Error:(35, 41) java: 找不到符号
      符号:Objenesis
    Error:(47, 23) java: 找不到符号
      符号:InstantiatorStrategy
      位置:org.springframework.objenesis.SpringObjenesis
    Error:(49, 60) java: 找不到符号
      符号:ObjectInstantiator
      位置:org.springframework.objenesis.SpringObjenesis
    Error:(68, 32) java: 找不到符号
      符号:InstantiatorStrategy
      位置:org.springframework.objenesis.SpringObjenesis
    Error:(110, 20) java: 找不到符号
      符号:ObjectInstantiator
      位置:org.springframework.objenesis.SpringObjenesis
    Error:(122, 23) java: 找不到符号
      符号:ObjectInstantiator
      位置:org.springframework.objenesis.SpringObjenesis
    Error:(69, 68) java: 找不到符号
      符号:StdInstantiatorStrategy
      位置:org.springframework.objenesis.SpringObjenesis
    Error:(111, 17) java: 找不到符号
      符号:ObjectInstantiator
      位置:org.springframework.objenesis.SpringObjenesis
    Error:(113, 25) java: 找不到符号
      符号:ObjectInstantiator
      位置:org.springframework.objenesis.SpringObjenesis
    Error:(119, 25) java: 找不到符号
      符号:ObjectInstantiator
      位置:org.springframework.objenesis.SpringObjenesis
    Error:(125, 25) java: 找不到符号
      符号:ObjectInstantiator
      位置:org.springframework.objenesis.SpringObjenesis
    Error:(131, 24) java: 找不到符号
      符号:ObjenesisException
      位置:org.springframework.objenesis.SpringObjenesis
    Error:(149, 35) java: 找不到符号
      符号:ObjenesisException
      位置:org.springframework.objenesis.SpringObjenesis
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46

    原因:
    为了避免第三方class冲突,spring把最新的cglib和objenesis重新打包jar并没有放在源码里。

    解决办法:
    gradle 执行 objenesisRepackJar 和 cglibRepackJar
    解决问题过程:
    打开系统cmd 命令行控制台 (注意:不要用idea的 Terminal ,我一直不成功)
    Win + R 输入cmd
    切换工作目录到 spring 源码工程的根目录下
    在这里插入图片描述
    执行

     gradle objenesisRepackJar
    
    • 1

     gradle cglibRepackJar
    
    • 1

    idea 再次编译源码工程 Build -> Build Project
    发现上述问题没有了

    1. spring源码导入IDEA构建时报org.springframework.oxm.jaxb.test不存在问题的解决方案(spring-oxm缺少castor和jaxb)
      在这里插入图片描述
      然后重新build一下即可.
    2. 找不到符号:类 JCacheCacheAspect、JtaAnnotationTransactionAspect、AnnotationTransactionAspect 、AnnotationCacheAspect 、AnnotationAsyncExecutionAspect 、AnnotationBeanConfigurerAspect 具体如下:
    D:\Idea2019\workspace-senior\spring-framework\spring-aspects\src\main\java\org\springframework\cache\aspectj\AspectJJCacheConfiguration.java
    Error:(42, 16) java: 找不到符号
      符号:JCacheCacheAspect
      位置:org.springframework.cache.aspectj.AspectJJCacheConfiguration
    Error:(43, 17) java: 找不到符号
      符号:JCacheCacheAspect
      位置:org.springframework.cache.aspectj.AspectJJCacheConfiguration
    Error:(43, 49) java: 找不到符号
      符号:   变量 JCacheCacheAspect
      位置:org.springframework.cache.aspectj.AspectJJCacheConfiguration
    D:\Idea2019\workspace-senior\spring-framework\spring-aspects\src\main\java\org\springframework\transaction\aspectj\AspectJJtaTransactionManagementConfiguration.java
    Error:(43, 16) java: 找不到符号
      符号:JtaAnnotationTransactionAspect
      位置:org.springframework.transaction.aspectj.AspectJJtaTransactionManagementConfiguration
    Error:(44, 17) java: 找不到符号
      符号:JtaAnnotationTransactionAspect
      位置:org.springframework.transaction.aspectj.AspectJJtaTransactionManagementConfiguration
    Error:(44, 59) java: 找不到符号
      符号:   变量 JtaAnnotationTransactionAspect
      位置:org.springframework.transaction.aspectj.AspectJJtaTransactionManagementConfiguration
    D:\Idea2019\workspace-senior\spring-framework\spring-aspects\src\main\java\org\springframework\transaction\aspectj\AspectJTransactionManagementConfiguration.java
    Error:(43, 16) java: 找不到符号
      符号:AnnotationTransactionAspect
      位置:org.springframework.transaction.aspectj.AspectJTransactionManagementConfiguration
    Error:(44, 17) java: 找不到符号
      符号:AnnotationTransactionAspect
      位置:org.springframework.transaction.aspectj.AspectJTransactionManagementConfiguration
    Error:(44, 56) java: 找不到符号
      符号:   变量 AnnotationTransactionAspect
      位置:org.springframework.transaction.aspectj.AspectJTransactionManagementConfiguration
    D:\Idea2019\workspace-senior\spring-framework\spring-aspects\src\main\java\org\springframework\cache\aspectj\AspectJCachingConfiguration.java
    Error:(42, 16) java: 找不到符号
      符号:AnnotationCacheAspect
      位置:org.springframework.cache.aspectj.AspectJCachingConfiguration
    Error:(43, 17) java: 找不到符号
      符号:AnnotationCacheAspect
      位置:org.springframework.cache.aspectj.AspectJCachingConfiguration
    Error:(43, 53) java: 找不到符号
      符号:   变量 AnnotationCacheAspect
      位置:org.springframework.cache.aspectj.AspectJCachingConfiguration
    D:\Idea2019\workspace-senior\spring-framework\spring-aspects\src\main\java\org\springframework\scheduling\aspectj\AspectJAsyncConfiguration.java
    Error:(44, 16) java: 找不到符号
      符号:AnnotationAsyncExecutionAspect
      位置:org.springframework.scheduling.aspectj.AspectJAsyncConfiguration
    Error:(45, 17) java: 找不到符号
      符号:AnnotationAsyncExecutionAspect
      位置:org.springframework.scheduling.aspectj.AspectJAsyncConfiguration
    Error:(45, 62) java: 找不到符号
      符号:   变量 AnnotationAsyncExecutionAspect
      位置:org.springframework.scheduling.aspectj.AspectJAsyncConfiguration
    D:\Idea2019\workspace-senior\spring-framework\spring-aspects\src\main\java\org\springframework\context\annotation\aspectj\SpringConfiguredConfiguration.java
    Error:(19, 49) java: 找不到符号
      符号:AnnotationBeanConfigurerAspect
      位置: 程序包 org.springframework.beans.factory.aspectj
    Error:(47, 16) java: 找不到符号
      符号:AnnotationBeanConfigurerAspect
      位置:org.springframework.context.annotation.aspectj.SpringConfiguredConfiguration
    Error:(48, 24) java: 找不到符号
      符号:   变量 AnnotationBeanConfigurerAspect
      位置:org.springframework.context.annotation.aspectj.SpringConfiguredConfiguration
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60

    原因:
    通过百度查询到问题原因是spring源码的AOP使用了aspectj,而java不识别aspectj
    下载AspectJ
    https://www.eclipse.org/aspectj/downloads.php

    在这里插入图片描述
    安装
    win10安装办法,在cmd窗口中执行
    在这里插入图片描述
    弹出
    在这里插入图片描述
    安装完
    在这里插入图片描述
    添加facet属性
    在这里插入图片描述
    在这里插入图片描述
    选择spring.spring-aop.main
    在这里插入图片描述
    按照上述步骤添加spring.spring-aspects.main
    最后的结果展示如图
    在这里插入图片描述
    更改编译器
    在这里插入图片描述
    在这里插入图片描述

    3、创建测试项目

    导入成功之后可以在project下创建一个自己的测试module

    1. 项目根目录右键 -> new -> module -> gradle
      在这里插入图片描述
    2. 在新项目的build.gradle下添加对spring模块的依赖,这里我先添加了spring-beans 和spring-core的依赖。
    dependencies {
        compile(project(":spring-beans"))
        compile(project(":spring-core"))
        testCompile group: 'junit', name: 'junit', version: '4.12'
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    1. 在新项目的src/main/resource下添加spring-config.xml文件
    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
    	   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    	   xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    	<!--把对象的创建交给spring来管理-->
    	<bean id="person" class="com.wts.Person">
    		<property name="id" value="1"></property>
    		<property name="name" value="zhangsan"></property>
    	</bean>
    </beans>
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    1. 创建测试bean和启动类
    public class Person {
    
    	private int id;
    
    	private String name;
    
    	public int getId() {
    		return id;
    	}
    
    	public void setId(int id) {
    		this.id = id;
    	}
    
    	public String getName() {
    		return name;
    	}
    
    	public void setName(String name) {
    		this.name = name;
    	}
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    public class Test {
    
    	public static void main(String[] args) {
    		ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
    		Person person = (Person) ac.getBean("person");
    		System.out.println(person);
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    在这里插入图片描述

    之后就可以愉快的调试spring源码了。

  • 相关阅读:
    JVM -运行时数据区 - 堆空间
    Ubuntu搭建Docker&docker-compose环境
    C++流插入和流提取的重载!
    数据库系统工程师难考吗?
    了解汽车ecu组成
    近几年RGBT论文汇总
    什么是渗透测试
    详解析构函数、拷贝构造函数
    基于STM32CUBEMX驱动TOF模块VL53l0x(3)----驱动多个VL53L0X
    OpenCV学习——绘图函数案例
  • 原文地址:https://blog.csdn.net/wts563540/article/details/126686645