写点什么

windows 下修改、编译、构建 spring-framework4.1.8.RELEASE 源码

作者:程序员欣宸
  • 2022 年 6 月 06 日
  • 本文字数:6659 字

    阅读完需:约 22 分钟

windows下修改、编译、构建spring-framework4.1.8.RELEASE源码

欢迎访问我的 GitHub

这里分类和汇总了欣宸的全部原创(含配套源码):https://github.com/zq2599/blog_demos

本篇概览

环境信息

  • 实战涉及的版本如下:


  1. 操作系统:win10 64;

  2. JDK:1.8.0_144;

  3. Maven:3.5.0;

  4. IntelliJ IDEA:2018.1.5(Ultimate Edition);

全文概要

  • 本次实战所有步骤如下:


  1. 下载 spring-framwork 源码,用 IDEA 打开此工程;

  2. 修改 spring-framework 中的类,添加代码;

  3. 编译构建 spring-framework,添加到本地 maven 仓库;

  4. 基于 maven 创建一个新的 demo,使用本地仓库的 spring-framework;

  5. 执行 demo 工程验证修改的代码已经生效;


  • 接下来开始实战吧;

下载 spring-framework 源码,用 IDEA 打开此工程

  • 打开 spring-framework 在 GitHub 上的 release 列表,地址是:https://github.com/spring-projects/spring-framework/releases ,下载 4.1.8.RELEASE 版本,如下图红框所示:


  • 解压后,用 Intellij IDEA 以 Gradle 工程的形式导入,Gradle 版本记得使用 2.14.1,如下图:


修改 spring-framework 中的类

  • 本次修改的类是 PropertyPlaceholderHelper.java,这个类用来替换字符串中的占位符,本次修改源码的目的如下:


  1. 将替换前后的字符串打印出来用于对比;

  2. 将调用堆栈打印出来,这样我们在学习 spring 源码时,可以知道处理占位符的时机和位置;


  • 对 PropertyPlaceholderHelper.java 的具体修改如下所示:

  • 新增一个 private 方法,用于打印当前堆栈位置:


private void printTrack(String prefix){    StackTraceElement[] st = Thread.currentThread().getStackTrace();    if(st==null){        logger.info("invalid stack");        return;    }
StringBuffer sbf =new StringBuffer();
for(StackTraceElement e:st){ if(sbf.length()>0){ sbf.append(" <- "); sbf.append(System.getProperty("line.separator")); } sbf.append(java.text.MessageFormat.format("{0}.{1}() {2}" ,e.getClassName() ,e.getMethodName() ,e.getLineNumber())); } logger.info(prefix + "\n" + sbf.toString());}
复制代码


  • 找到方法 parseStringValue,注意是 protected 类型的那个,在该方法的起始位置添加如下两行代码:


protected String parseStringValue(            String strVal, PlaceholderResolver placeholderResolver, Set<String> visitedPlaceholders) {    printTrack("start parseStringValue");    logger.info("before parse : [" + strVal + "]");
复制代码


  • 上述代码先是将 parseStringValue 被调用的堆栈打印出来,接着将入参 strVal 打印出来;

  • 在上一步中的 parseStringValue 方法的结束位置,在 return 之前增加一行代码,将处理后的字符串打印出来,如下:


    logger.info("after parse : [" + result + "]");    return result.toString();}
复制代码


  • 为了避免当前电脑的其他项目用到我们构建的 spring 版本,我们把版本号改掉,打开 gradle.properties 文件,修改版本号为"4.1.88.RELEASE",如下:


version=4.1.88.RELEASE
复制代码

编译构建 spring-framework

  • 用命令 build -x test 编译和构建工程,操作如下图所示:

  • 等待构建完成之后,用命令 install 将构建的 jar 部署到本地 maven 仓库中,如下图:

  • 去本地 maven 仓库看看,果然已经有文件了,如下图:

创建 demo,使用本地仓库的 spring-framework

  • 基于 maven 创建一个 java 应用,以下是步骤:

  • pom.xml 内容如下:


<?xml version="1.0" encoding="UTF-8"?><project xmlns="http://maven.apache.org/POM/4.0.0"         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">    <modelVersion>4.0.0</modelVersion>
<groupId>com.bolingcavalry</groupId> <artifactId>springcoredemo</artifactId> <version>1.0-SNAPSHOT</version>
<dependencies> <!-- Spring framework --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> <version>4.1.88.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>4.1.88.RELEASE</version> </dependency> </dependencies>
</project>
复制代码


  • 新增文件:src/main/resources/applicationContext.xml,用于配置 bean,内容如下:


<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans"       xmlns:mvc="http://www.springframework.org/schema/mvc"       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"       xmlns:p="http://www.springframework.org/schema/p"       xmlns:aop="http://www.springframework.org/schema/aop"       xmlns:tx="http://www.springframework.org/schema/tx"       xmlns:context="http://www.springframework.org/schema/context"       xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/mvchttp://www.springframework.org/schema/mvc/spring-mvc.xsdhttp://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop.xsdhttp://www.springframework.org/schema/tx    http://www.springframework.org/schema/tx/spring-tx-4.0.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context.xsd">
<beans> <bean class="com.bolingcavalry.bean.Simple"></bean> </beans></beans>
复制代码


  • 创建一个类:com.bolingcavalry.bean.Simple.java:


public class Simple {    public void execute() {        System.out.println("Simple execute method");    }}
复制代码


  • 创建启动类 com.bolingcavalry.DemoApplication.java:


public class DemoApplication {
public static void main(String[] args) { ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("${CONFIG_PATH}"); Simple bean = context.getBean(Simple.class); bean.execute(); context.close(); }}
复制代码


  • 注意以上代码中有个变量**${CONFIG_PATH}**,这个变量的值不在代码和配置文件中,留待运行的时候再设置;

  • 运行 DemoApplication.java 的时候,注意传入环境变量 CONFIG_PATH 的值,在 IDEAL 上的做法如下,点击红框中的"Edit Configurations...":


  • 如下图,点击红框中的按钮:


  • 如下图,点击红框中的加号,然后添加一个键值对,Name 是"CONFIG_PATH",Value 是"classpath:applicationContext.xml"


  • 配置完毕后,点击下图红框中的绿色三角形按钮,即可运行 DemoApplication 的 main 方法,并且刚刚设置的环境变量也生效了:


  • 运行结果如下:


C:\jdk\bin\java.exe -javaagent:C:\software\JetBrains\IntelliJIDEA\lib\idea_rt.jar=60748:C:\software\JetBrains\IntelliJIDEA\bin -Dfile.encoding=UTF-8 -classpath C:\jdk\jre\lib\charsets.jar;C:\jdk\jre\lib\deploy.jar;C:\jdk\jre\lib\ext\access-bridge-64.jar;C:\jdk\jre\lib\ext\cldrdata.jar;C:\jdk\jre\lib\ext\dnsns.jar;C:\jdk\jre\lib\ext\jaccess.jar;C:\jdk\jre\lib\ext\jfxrt.jar;C:\jdk\jre\lib\ext\localedata.jar;C:\jdk\jre\lib\ext\nashorn.jar;C:\jdk\jre\lib\ext\sunec.jar;C:\jdk\jre\lib\ext\sunjce_provider.jar;C:\jdk\jre\lib\ext\sunmscapi.jar;C:\jdk\jre\lib\ext\sunpkcs11.jar;C:\jdk\jre\lib\ext\zipfs.jar;C:\jdk\jre\lib\javaws.jar;C:\jdk\jre\lib\jce.jar;C:\jdk\jre\lib\jfr.jar;C:\jdk\jre\lib\jfxswt.jar;C:\jdk\jre\lib\jsse.jar;C:\jdk\jre\lib\management-agent.jar;C:\jdk\jre\lib\plugin.jar;C:\jdk\jre\lib\resources.jar;C:\jdk\jre\lib\rt.jar;D:\github\blog_demos\springcoredemo\target\classes;C:\Users\12167\.m2\repository\org\springframework\spring-core\4.1.88.RELEASE\spring-core-4.1.88.RELEASE.jar;C:\Users\12167\.m2\repository\commons-logging\commons-logging\1.2\commons-logging-1.2.jar;C:\Users\12167\.m2\repository\org\springframework\spring-context\4.1.88.RELEASE\spring-context-4.1.88.RELEASE.jar;C:\Users\12167\.m2\repository\org\springframework\spring-aop\4.1.88.RELEASE\spring-aop-4.1.88.RELEASE.jar;C:\Users\12167\.m2\repository\aopalliance\aopalliance\1.0\aopalliance-1.0.jar;C:\Users\12167\.m2\repository\org\springframework\spring-beans\4.1.88.RELEASE\spring-beans-4.1.88.RELEASE.jar;C:\Users\12167\.m2\repository\org\springframework\spring-expression\4.1.88.RELEASE\spring-expression-4.1.88.RELEASE.jar com.bolingcavalry.DemoApplication七月 07, 2018 7:18:14 下午 org.springframework.util.PropertyPlaceholderHelper printTrack信息: start parseStringValuejava.lang.Thread.getStackTrace() 1,559 <- org.springframework.util.PropertyPlaceholderHelper.printTrack() 231 <- org.springframework.util.PropertyPlaceholderHelper.parseStringValue() 132 <- org.springframework.util.PropertyPlaceholderHelper.replacePlaceholders() 126 <- org.springframework.core.env.AbstractPropertyResolver.doResolvePlaceholders() 204 <- org.springframework.core.env.AbstractPropertyResolver.resolveRequiredPlaceholders() 178 <- org.springframework.core.env.AbstractEnvironment.resolveRequiredPlaceholders() 571 <- org.springframework.context.support.AbstractRefreshableConfigApplicationContext.resolvePath() 122 <- org.springframework.context.support.AbstractRefreshableConfigApplicationContext.setConfigLocations() 80 <- org.springframework.context.support.ClassPathXmlApplicationContext.<init>() 137 <- org.springframework.context.support.ClassPathXmlApplicationContext.<init>() 83 <- com.bolingcavalry.DemoApplication.main() 14七月 07, 2018 7:18:14 下午 org.springframework.util.PropertyPlaceholderHelper parseStringValue信息: before parse : [${CONFIG_PATH}]七月 07, 2018 7:18:14 下午 org.springframework.util.PropertyPlaceholderHelper printTrack信息: start parseStringValuejava.lang.Thread.getStackTrace() 1,559 <- org.springframework.util.PropertyPlaceholderHelper.printTrack() 231 <- org.springframework.util.PropertyPlaceholderHelper.parseStringValue() 132 <- org.springframework.util.PropertyPlaceholderHelper.parseStringValue() 148 <- org.springframework.util.PropertyPlaceholderHelper.replacePlaceholders() 126 <- org.springframework.core.env.AbstractPropertyResolver.doResolvePlaceholders() 204 <- org.springframework.core.env.AbstractPropertyResolver.resolveRequiredPlaceholders() 178 <- org.springframework.core.env.AbstractEnvironment.resolveRequiredPlaceholders() 571 <- org.springframework.context.support.AbstractRefreshableConfigApplicationContext.resolvePath() 122 <- org.springframework.context.support.AbstractRefreshableConfigApplicationContext.setConfigLocations() 80 <- org.springframework.context.support.ClassPathXmlApplicationContext.<init>() 137 <- org.springframework.context.support.ClassPathXmlApplicationContext.<init>() 83 <- com.bolingcavalry.DemoApplication.main() 14七月 07, 2018 7:18:14 下午 org.springframework.util.PropertyPlaceholderHelper parseStringValue信息: before parse : [CONFIG_PATH]七月 07, 2018 7:18:14 下午 org.springframework.util.PropertyPlaceholderHelper parseStringValue信息: after parse : [CONFIG_PATH]七月 07, 2018 7:18:14 下午 org.springframework.util.PropertyPlaceholderHelper printTrack信息: start parseStringValuejava.lang.Thread.getStackTrace() 1,559 <- org.springframework.util.PropertyPlaceholderHelper.printTrack() 231 <- org.springframework.util.PropertyPlaceholderHelper.parseStringValue() 132 <- org.springframework.util.PropertyPlaceholderHelper.parseStringValue() 165 <- org.springframework.util.PropertyPlaceholderHelper.replacePlaceholders() 126 <- org.springframework.core.env.AbstractPropertyResolver.doResolvePlaceholders() 204 <- org.springframework.core.env.AbstractPropertyResolver.resolveRequiredPlaceholders() 178 <- org.springframework.core.env.AbstractEnvironment.resolveRequiredPlaceholders() 571 <- org.springframework.context.support.AbstractRefreshableConfigApplicationContext.resolvePath() 122 <- org.springframework.context.support.AbstractRefreshableConfigApplicationContext.setConfigLocations() 80 <- org.springframework.context.support.ClassPathXmlApplicationContext.<init>() 137 <- org.springframework.context.support.ClassPathXmlApplicationContext.<init>() 83 <- com.bolingcavalry.DemoApplication.main() 14七月 07, 2018 7:18:14 下午 org.springframework.util.PropertyPlaceholderHelper parseStringValue信息: before parse : [classpath:applicationContext.xml]七月 07, 2018 7:18:14 下午 org.springframework.util.PropertyPlaceholderHelper parseStringValue信息: after parse : [classpath:applicationContext.xml]七月 07, 2018 7:18:14 下午 org.springframework.util.PropertyPlaceholderHelper parseStringValue信息: after parse : [classpath:applicationContext.xml]七月 07, 2018 7:18:14 下午 org.springframework.context.support.ClassPathXmlApplicationContext prepareRefresh信息: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@20ad9418: startup date [Sat Jul 07 19:18:14 GMT+08:00 2018]; root of context hierarchy七月 07, 2018 7:18:14 下午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions信息: Loading XML bean definitions from class path resource [applicationContext.xml]七月 07, 2018 7:18:14 下午 org.springframework.context.support.ClassPathXmlApplicationContext doClose信息: Closing org.springframework.context.support.ClassPathXmlApplicationContext@20ad9418: startup date [Sat Jul 07 19:18:14 GMT+08:00 2018]; root of context hierarchySimple execute method
Process finished with exit code 0
复制代码


  • 上述结果我们看到堆栈信息,能反映出该方法在运行时的调用情况,另外 before parse after parse 反映了解析前和解析后的字符串变化,至于为何堆栈会打印多次,那是因为 parseStringValue 方法自身存在迭代调用的情况,每次都会打印,这从堆栈信息中也能看出来(parseStringValue() 148 );

  • 这个 demo 的源码可以在 github 下载,地址和链接信息如下表所示:



  • 这个 git 项目中有多个文件夹,本章源码在 springcoredemo 文件夹中,如下图红框所示:



  • 至此,修改 spring-framwork 源码的实战就完成了,希望您在学习 spring-framwork 的时候也能动手修改和构建自己有兴趣的地方,也希望本文能给您一些参考;

欢迎关注 InfoQ:程序员欣宸

学习路上,你不孤单,欣宸原创一路相伴...

发布于: 2022 年 06 月 06 日阅读数: 34
用户头像

搜索"程序员欣宸",一起畅游Java宇宙 2018.04.19 加入

前腾讯、前阿里员工,从事Java后台工作,对Docker和Kubernetes充满热爱,所有文章均为作者原创,个人Github:https://github.com/zq2599/blog_demos

评论

发布
暂无评论
windows下修改、编译、构建spring-framework4.1.8.RELEASE源码_Java_程序员欣宸_InfoQ写作社区