“This article has participated in the good article call order activity, click to see: back end, big front end double track submission, 20,000 yuan prize pool for you to challenge!”
Springboot
中 AOP
Cause of failure
Today 4YE is here to share a little practical experience with friends. · ∀ ·) Blue
Actual review
(I can’t believe I took so long to write this article… 😵)
Mainly on a Sunday (2020.6.6) in the technology group to see a brother asked
“How to catch custom exceptions with facets?” ( ̄▽ ̄)”
At that time, I thought, isn’t it common to catch exceptions? I often use this global exception catch, so I sent him a small example on my GitHub (mainly the ControllerAdvice annotation), as shown in 👇
The result old brother after a period of time to add me, also asked me if I have time to help to look, also want to call me, MY heart at that time is
Is it so urgent?
When I came back in the evening, it took me two hours to understand why this AOP did not work. Why was the exception not caught?
Now enter the topic 👉 (overall project introduction)
Maven project structure diagram
In this project, maven project adopts multi-module construction, parent and child structure, and the parent Maven unified management of these public packages, as well as the overall version attribute configuration of the project
There are two modules, starter module and core module. The starter module depends on the core module. The overall picture is as follows: 👇
Submodule Introduction
I wonder if you can smell anything when you see the starter above.
At first I thought it would be a common custom starter, but it’s a little different. There’s only a single spring.factories, which clearly uses Springboot’s SPI mechanism.
This is introduced in our previous 👉 Springboot auto-assembly principle exploration article, friends can go to see ~😄
The core parts of the two modules are expanded as follows: 👇
Core project description: Non-Web project only has service, no startup class, etc
👉 because core module is not a Web project!! , so the ControllerAdvice is certainly can’t use, after all, it is in the web in the package, we generally in the web project with the @ ExceptionHandler (Exception. Class) to realize global Exception handling, and then make unified handling.
👉 Springboot’s SPI mechanism tells us that when a Springboot project starts, it scans the meta-INF /spring.factories (including jars) in each project and reads the configuration information in the factories into memory. The auto-configuration will filter these classes according to certain conditions, and finally create the corresponding classes to complete the auto-assembly.
It is obvious that the injection of related beans is done through automatic configuration.
Configuration Class Description
So, with that basic information in mind, we can turn our eyes to xxxConfig, which mimics 👇
Next comes the aspect configuration in the project, such as the small example I wrote earlier: 👇
Code on my GitHub:
Github.com/RyzeYang/sp…
Catch by exception notification
Other than the two above, no other configuration is used in the project!
The question
This is where the problem comes in, after the sections are defined, they don’t work in the project! Everything else works!
So I kept thinking, why is this? It’s already defined…
Finally, I gave it a try, adding this parameter to the YAML configuration file
spring:
aop:
auto: true
Copy the code
Because under the impression that this defaults to true, the @enableAspectJAutoProxy will be used by default, without us having to manually add the @enableAspectJAutoProxy annotation (we haven’t manually added this annotation before) 🐖
It didn’t work…
So I decided to manually add it to the xxxConfig config class, but it didn’t work…
@componentScan (basePackages = “com.xxx.xxx”)
And it worked!
So I rushed at 23:59 after the revised document sent to the old brother, but found that he actually fell asleep ha ha ha
The problem analysis
After solving the problem, we can find the problem in the following two points 👇
- Section not registered with
SpringIOC
In the container - I’m not using this
@EnableAspectJAutoProxy
@componentScan (basePackages = “com.xxx.xxx”)
After all, I didn’t need to add it manually before, and from the configuration description, it is enabled by default even if we don’t have the configuration, and it will automatically use this annotation
So do you know the problem of step 2 😄
The @enableAutoConfiguration annotation is the most important one in our SpringBootApplication composite annotation. And that’s what’s going to turn on this auto-assembly of ours.
At this time, I have to move this article out 👉 Springboot auto-assembly principle exploration haha
So let’s take a look at the CONFIGURATION class that AOP auassemble
Configuration classes for AOP auto-assembly
The source code of AopAutoConfiguration is as follows: 👇
There’s a conditional comment at the beginning
@ConditionalOnProperty(prefix = "spring.aop", name = "auto", havingValue = "true", matchIfMissing = true)
Copy the code
HavingValue = “true” means that the value is valid only if it is true
MatchIfMissing = true matchIfMissing = true
Then let’s put our eyes to the first: a static inner class AspectJAutoProxyingConfiguration
As shown in figure 👉 :
If proxyTargetClass is true, it uses cglib. If false, it uses JDK dynamic proxy
Then look at the last of the static inner class: ClassProxyingConfiguration
Can find it here is conditional and AspectJAutoProxyingConfiguration, on the contrary, when there is no class this Advice, help us to register the agent to the IOC
After looking at the AOP auassemble class, we can see that when we use the @EnableAutoConfiguration auassemble annotation and introduce the AOP package, it will automatically assemble the AopAutoConfiguration for us. It uses @enableAspectJAutoProxy, so we usually don’t have to add this annotation manually.
How to test
Hey hey, again a small problem test small partner 😝
SpringBootApplication is not used in the core module, and @enableAutoConfiguration is not used, so this SPI is not useful without auto-assembly. How do we test it in the project
SpringBootTest(classes = xxxConfiguration.class)
With this class, we can directly specify and instantiate the configuration class
I also report a mistake just know ha ha 😝
conclusion
Hey hey, old custom, draw a picture summary below 👇
Thinking of the February
Knowledge map in
So, this time to share this, like friends remember to click like it ~ next time to see the situation and share one of the following 😝
- Springboot Custom starter
- Implement plug-ins using AOP
- The Spring source
The last
Welcome to explore the problem together
If you think this article is good, please support it with more likes 😝
Let’s start this unexpected meeting! ~
Please leave a message! Thanks for your support! ヾ(≧▽≦*)o
I’m 4ye. Next time we should… See you soon!! 😆