preface

Last Monday, my friend reported a problem to me, their project can run locally, but the online environment, reported an error. The error log is as follows:

Could not find result map cn.mycs.server.persistence.dao.UserMapper.BaseResultMap
Copy the code

To tell you the truth, I’m so busy every day, I don’t want to see this kind of direct exception thrown out. But his words changed my mind completely.

First came these key words.

  • Unsolvable bugs

Before fat repeatedly emphasized, we look at the source, is to solve the problem, rather than simply to interview pretend force, if the search engine can be solved literally search the first page, that also see the source code is really a perfect way to avoid the most efficient way to solve the problem

  • Specific circumstances arise

It can be seen from the chat records that this problem is also limited by environmental conditions, which is not convenient to simulate. The most important thing is that Fei Chao cannot directly connect to his company’s environment to help him see the problem.

Abnormal things will be demon, plus he is fat toward the public number fans (delimit key), that can only come to a wave of monster hunt!

Listening, asking and

In fact, many people after writing code for a few years often sigh that it is really easy to write code, is to use a variety of frameworks, stacking wood type programming. In fact, the reason why they have such a sigh, the main reason is that the challenges encountered in the work are not enough. So much so that they think the principle, the source code these things are pure interview bullshit.

Of course will look at the source to solve the search engine can not solve the problem, or far from enough. High concurrency. There will be a lot of difficult to reproduce the problem, this time, must learn a new skill, is through the log, through eye compilation, static look at the source code.

So I asked and got the error log as follows:

Mybatis plus: Mybatis plus: Mybatis plus: Mybatis plus: Mybatis Plus It doesn’t matter, said before, static look at the source code, look compiled! So I started a new demo and introduced the dependencies.

Nine shallow depth

Highlight the exception stack shown above

As you can see from the three highlights I’ve highlighted plus elementary school simple English, BaseResultMap was not found when userPersonalmapper.xml was parsed. Another point, as you can see from the emphasis in my markup, is that this BaseResultMap is declared in another XML, usermapper.xml.

Userpersonalmapper. XML was loaded before usermapper. XML was loaded. The BaseResultMap defined by usermapper. XML cannot be found

Frankly, there’s nothing wrong with this, and it’s perfectly reasonable

But the bottom line is, local running is fine. How come when I run locally, there is no error, this you how to explain?

A lot of friends asked me how to look at the source code, so I now hand in hand, according to the only clues, nine shallow a deep straight into the source code.

The log tells us that it was 583, and then mapperLocations are very obvious, because we’re configuring our Mapper set, and he’s going through every mapper from that set to parse it.

So the key question is, we’re looking at the code statically, we’re compiling, we can’t hit the breakpoint, so when did this mapper get set, what values did it get set? In order to do not retain to the public number fans transmission heart course, I will be detailed screenshots.

The following tips are entirely a matter of using IDEA

1. Check where the variable is referenced

2. See where the method is called

Finally, let’s get to the core processing logic

From resolveMapperLocations and PathMatchingResourcePatternResolver these two class names and return values Resource [], even if be the word apart a a translation can probably guess, this is according to the configuration / *. The XML configuration, to find To all XML resources. Resource[] is an array, and arrays are ordered, so the order of the mapper in the array will determine whether our previous guess is correct.

Verify the guess

So I asked the friend to add the log to test my guess

He then posts the logs that work and the logs that don’t, as follows

Usermapper.xml was loaded last, which naturally caused the XML to be parsed last during traversal, so the BaseResultMap defined on the XML could not be used by the previous load

But the point is, again, it’s not clear why local is ok. Why is the loading order of local runs OK?

A simple

Now range is very small, we used the conjecture, to verify the hypothesis, has taken the target gradually narrowed, now it is a problem, as long as the clear PathMatchingResourcePatternResolver logic, everything will be suddenly enlightened

Because of the online environment, are into jar dependent startup. Native classes, so they branch differently

Deep thinking

To see a problem, we must think deeply. For example, there should be some question here is why fat Chao knows. They branch differently. Say again the man’s pledge of eternal love is false, I how know fat toward say is true.

Frankly speaking, the best time to focus on fat is two years ago, the second is now, if you start from the source code analysis series of articles on fat, trained eyes compiled, static look at the source code, there is naturally no doubt

If you’ve missed the perfect time to pay attention, I’ll give you another creepy way to do it. You put the PathMatchingResourcePatternResolver this kind of copy, change a name. Such as FeichaoPathMatchingResourcePatternResolver. Then type in some crude log information, as shown below

Then you start locally, and jar starts, and see the log output.

So what’s the difference between these two branches? The branch of code that this native code follows has a very important piece of logic

He’s going to sort by resource files, so by what rules

Let’s take a look at some of the common development tools we’ve introduced in previous articles.

Why has the place never reappeared? The userMapper. XML file is always loaded before userPersonalmapper. XML because the logic of the source file is sorted by default.

Standardize development and reject accidental success

And frankly, I think it’s very unregulated to have two Mapper references. Since the sorting of resource files into jars is very uncontrollable, it may be affected by different build tools such as Maven and Gradle, or even by the version of the build tool such as Maven, or by the environment such as Windows, Linux, etc. The reason we didn’t find any problems during local development was sheer success. Let’s finally verify the problem with a simple JDK Api. Let’s take a jar that starts and reports errors

Obviously, the order of the resource files in the two jars is different. Therefore, if the mapper is written according to his method, it may appear that because of the high maven version of environment A, the optimization and other factors, the default into jar according to the file name order, but in the other environment B, the resources into jar are disordered. The problem description might then be cryptic: “Same code, environment A package always works, environment B package occasionally fails.” That’s a term I use a lot in teams, accidental success.

Write in the last

Fertilizer toward is a focus on principle, source code, development skills of technical public number, number of original thematic source code analysis, real scene source code principle combat (key).Scan the following QR codePay attention to fat, let should build rocket you, no longer screw!