Modify and build the spring-framework source code

In the process of learning spring, it is a good learning method to modify the source code and verify the results. It is a good way to impress yourself. Today I will modify the spring-framework source code, then compile and build, and finally write a demo project. Verify successful construction;

Environmental information

The versions involved in actual combat are as follows:

  1. Operating system: win10 64;

  2. JDK:1.8.0_144;

  3. Maven:3.5.0;

  4. IntelliJ IDEA:2018.1.5(Ultimate Edition);

Full text summary

All steps in this actual combat are as follows:

  1. Download the spring-framwork source code and use IDEA to open the project;

  2. Modify the class in spring-framework and add code;

  3. Compile and build spring-framework, add to the local maven repository;

  4. Create a new demo based on maven, using the spring-framework of the local warehouse;

  5. Perform the demo project to verify that the modified code has taken effect;

Let's start the actual combat;

Download the spring-framework source code and use IDEA to open the project

  1. Open the release list of spring-framework on GitHub at https://github.com/spring-projects/spring-framework/releases, download the 4.1.8.RELEASE version, as shown in the red box below:

  2. After decompression, use Intellij IDEA to import in the form of Gradle project. Gradle version remember to use 2.14.1, as shown below:

Modify the class in spring-framework

The class modified this time is PropertyPlaceholderHelper.java. This class is used to replace the placeholders in the string. The purpose of this modification of the source code is as follows:

  1. Print the strings before and after replacement for comparison;

  2. Print out the call stack, so that when we learn the spring source code, we can know the timing and location of the placeholders;

The specific modifications to PropertyPlaceholderHelper.java are as follows:

  1. Added a private method to print the current stack position:

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());
}
  1. Find the method parseStringValue , pay attention to the protected type, add the following two lines of code at the beginning of the method:

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

The above code first prints the stack where parseStringValue is called, and then prints the input parameter strVal ; 3. At the end of the parseStringValue method in the previous step, add a line of code before return to print the processed string, as follows :

	logger.info("after parse : [" + result + "]");
	return result.toString();
}
  1. In order to prevent other projects on the current computer from using the spring version we built, we changed the version number, opened the gradle.properties file, and modified the version number to "4.1.88.RELEASE", as follows:

version=4.1.88.RELEASE

Compile and build spring-framework

  1. Compile and build the project with the command build -x test , the operation is as shown in the figure below:

  2. After waiting for the build to complete, use the command install to deploy the built jar to the local maven repository, as shown below:

  3. Go to the local maven warehouse to see, there are already files, as shown below:

Create demo, use spring-framework of local warehouse

Create a java application based on maven, the following are the steps:

  1. The content of pom.xml is as follows:

<?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>
  1. New file: src / main / resources / applicationContext.xml, used to configure the bean, the content is as follows:

<?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/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/tx
 	http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">


    <beans>
        <bean class="com.bolingcavalry.bean.Simple"></bean>
    </beans>
</beans>
  1. Create a class: com.bolingcavalry.bean.Simple.java:

public class Simple {
    public void execute() {
        System.out.println("Simple execute method");
    }
}
  1. Create the startup class 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();
    }
}

Note that there is a variable $ {CONFIG_PATH} in the above code. The value of this variable is not in the code and configuration file, and it is set when it is run; The above method is as follows, click "Edit Configurations ..." in the red box:

  1. As shown below, click the button in the red box:

  2. As shown below, click the plus sign in the red box, and then add a key-value pair, Name is "CONFIG_PATH", Value is "classpath: applicationContext.xml"

  3. After the configuration, click the green triangle button in the red box below to run the main method of DemoApplication, and the environment variables that have just been set also take effect:

  4. The results are as follows:

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 parseStringValue
java.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 parseStringValue
java.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 parseStringValue
java.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 hierarchy
Simple execute method


Process finished with exit code 0

In the above results, we can see the stack information, which can reflect the call of the method at runtime. In addition, before parse and after parse reflect the string changes before and after parsing. As for why the stack is printed multiple times, it is because parseStringValue The method itself is called iteratively and will be printed every time, which can also be seen from the stack information (parseStringValue () 148);

The source code of this demo can be downloaded from github. The address and link information are shown in the table below:

name link Remarks
Project Homepage https://github.com/zq2599/blog_demos The project's homepage on GitHub
git repository address (https) https://github.com/zq2599/blog_demos.git The warehouse address of the project source code, https protocol
git repository address (ssh) [email protected]:zq2599/blog_demos.git The warehouse address of the project source code, ssh protocol

There are multiple folders in this git project. The source code of this chapter is in the springcoredemo folder, as shown in the red box below:

At this point, the actual combat to modify the spring-framwork source code is completed. I hope that you can also modify and build your own places of interest when learning spring-framwork. I hope this article can give you some reference;

Published 376 original articles · praised 986 · 1.28 million views

Guess you like

Origin blog.csdn.net/boling_cavalry/article/details/105384287