Spring source code reading notes

background

As a Java developer, no matter at work, chatting with colleagues, or in an interview, I have to talk about a framework: Spring. In the interview, I almost always ask so many questions, such as Bean life cycle, three-level cache, and cycle dependence on these questions.

We’ve all memorized a lot of interview questions and forgotten about them, but we still have to look at the source code. Before writing this article, I promise I haven’t seen the source code for Spring. This series sort of takes you from scratch.

My current source version is 5.3.16. Currently, it is the latest version on Github

So let’s get started.

Spring generates the Context process overview

Before reading the source code, you need to find the entry to the source code.

Start with a simple spring launcher.

public class Main {
	public static void main(String[] args) {
		ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("application.xml"); System.out.println(context); }}Copy the code

      
<beans xmlns="http://www.springframework.org/schema/beans"
	   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	   xmlns:context="http://www.springframework.org/schema/context"
	   xsi:schemaLocation="Http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

	<bean class="org.springframework.study.bean.FirstBean"></bean>
	<bean class="org.springframework.study.bean.SecondBean"></bean>

</beans>
Copy the code

Take a look at the entire method call flow at Spring startup.

As you can see from the call diagram above, the Refresh method is the key, but I have no idea what all these methods do.

Before we can actually read the code, we need to take a look at the class we are designing. And you get a picture that looks like this.

We don’t care what methods and attributes are in these classes, we can append them when we read them. So let’s go to the first method on our first Spring startup.

Super constructor

public ClassPathXmlApplicationContext(String configLocation) throws BeansException {
	this(new String[] {configLocation}, true.null);
}

public ClassPathXmlApplicationContext(
		String[] configLocations, boolean refresh, @Nullable ApplicationContext parent)
		throws BeansException {
	super(parent); // Parent is null when first entered
	setConfigLocations(configLocations);
	if(refresh) { refresh(); }}Copy the code

Seeing this method, dive right into super construction to see what’s going on

public AbstractXmlApplicationContext(@Nullable ApplicationContext parent) {
	super(parent);
}


public AbstractRefreshableConfigApplicationContext(@Nullable ApplicationContext parent) {
	super(parent);
}

public AbstractRefreshableApplicationContext(@Nullable ApplicationContext parent) {
	super(parent);
}


public AbstractApplicationContext(@Nullable ApplicationContext parent) {
	this(a); setParent(parent); }Copy the code

When it comes to getting the AbstractApplicationContext, changed, and call his own no arguments.

	public AbstractApplicationContext(a) {
		this.resourcePatternResolver = getResourcePatternResolver();
	}

	// Return ResourcePatternResolver to resolve the location pattern into the resource instance. The default is one
        / / {@ link org. Springframework. Core. IO. Support. PathMatchingResourcePatternResolver},
	protected ResourcePatternResolver getResourcePatternResolver(a) {
		return new PathMatchingResourcePatternResolver(this);
	}
	
	public PathMatchingResourcePatternResolver(ResourceLoader resourceLoader) {
		Assert.notNull(resourceLoader, "ResourceLoader must not be null");
		this.resourceLoader = resourceLoader;
	}
Copy the code

This method makes a ResourceLoader, so why can ApplicationContext be passed to ResourceLoader? As you can see from the class diagram above, AbstractContext extends a DefaultResourceLoader. As for what this ResourceLoader does, I have a cursory look at its getResources method and see that it is the loader that gets the resource files. Let’s go back to the code above and keep going.

    public AbstractApplicationContext(@Nullable ApplicationContext parent) {
    	this(a); setParent(parent); }@Override
	public void setParent(@Nullable ApplicationContext parent) {
		this.parent = parent;
		if(parent ! =null) {
                // Get the environment information
                    Environment parentEnvironment = parent.getEnvironment();
			if (parentEnvironment instanceof ConfigurableEnvironment) {
                            ConfigurableEnvironment sets the merge operationgetEnvironment().merge((ConfigurableEnvironment) parentEnvironment); }}}Copy the code

As the project has just started, here to pass null, found here, read a lonely 😂, can skip, we roughly read, if the quality of the case he will do some of the operation. Get the environment information and, if you are configuring the environment class, trigger a merge operation. Just to make a quick note of it, I have an idea in my head.

Next, go back to the constructor of the ClassPathXmlApplication.

setConfigLocations

    public void setConfigLocations(@Nullable String... locations) {
		if(locations ! =null) {
			Assert.noNullElements(locations, "Config locations must not be null");
			this.configLocations = new String[locations.length];
			for (int i = 0; i < locations.length; i++) {
				this.configLocations[i] = resolvePath(locations[i]).trim(); }}else {
			this.configLocations = null; }}Copy the code

This is a very simple piece of code, just doing an assignment to configLocations, which will probably be used later.

Come to an end

Because there are so many points involved in the Refresh method, this article starts here.

So far, the class diagram looks like this