Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

How to understand the extended implementation of Spring source code by MyBatis in principle

2025-01-19 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Internet Technology >

Share

Shulou(Shulou.com)06/01 Report--

Today, I will talk to you about how to understand MyBatis's extended implementation of Spring source code in principle, which may not be well understood by many people. in order to make you understand better, the editor has summarized the following content for you. I hope you can get something according to this article.

Today we will probably explain an extended idea of MyBatis for Spring from the following points!

First, what is FactoryBean?

First of all, we need to know at least one thing, that is, a general structure of FactoryBean:

The general structure of FactoryBean

As you can see, there are three methods for the entire FactoryBean:

GetObject (): returns the real object created specifically! GetObjectType (): returns the type of object that was created! IsSingleton (): whether the object created is a singleton object!

At this point, at least we already know that we can produce an object through a FactoryBean, and we can get the type of the object and whether the object is singleton or not! But without Spring, it's nothing, so what is Spring encapsulation for?

1. Custom Spring instantiated bean

It is because of the existence of FactoryBean that we can intervene or change the process of creating a Bean! Oh, why do you say that? Let me give you an example:

Take the commonly used MyBatis as an example, we all know that the use of MyBatis generally uses an interface to map a XML file. MyBatis dynamically generates an implementation class for the interface through a dynamic proxy, so that we can directly call the logic through the interface!

But after MyBatis is managed by Spring, have you ever wondered if we don't use the logic of MyBatis, and we can directly inject it into Service through a @ Autowired annotation, so where is the dynamic proxy logic of MyBatis done?

Yes, it was done in FactoryBean!

MyBatis uses FactoryBean for dynamic proxy

Students who are familiar with the use of MyBatis will be very familiar with this code. This is a piece of logic for MyBatis to generate dynamic agents through interfaces! So at least we know that Spring can FactoryBean call the getObject () method to create an object and manage it!

two。 Do not follow the lifecycle of Spring

Why is this? The author's idea is that precisely because the author of Spring wants to delegate power to the user and let the user implement the logic of creating a bean, Spring will not interfere too much in the instantiation process of the Bean, making the instantiation of a Bean completely realized by the user himself!

Unlike other normal bean, this class is not instantiated when the Spring container is initialized, but is similar to a lazy loading mechanism that is created and returned when it is retrieved! Whether it is a singleton or not depends on the return value of the isSingleton () method!

Of course, the created bean will also be cached, and logic such as AOP will also take effect on this class, of course, later!

3. Summary of FactoryBean

I believe that after reading the above article, you will have a basic understanding of Factory, let's summarize the following basic process of Spring calling it!

Invocation process of FactoryBean II. Custom scanner

Spring is just a project management framework, and it is also written in the JAVA language, so it must follow the specification of JAVA syntax! We can use Spring to help us manage some of the classes in our development process, and can automatically inject or AOP agents and other logic!

But do we find that Spring can only manage the classes under the package we specify, or some of the classes we add manually! And Spring has no way to help us scan some abstract classes or interfaces, but sometimes because of some special development, we have to break the original scanning process of Spring, for example, we need Spring to manage an interface for us, help us scan some specific annotated classes and other special requirements, at this time, we can not use the scanning logic provided for us by Spring. We need to customize a scanning logic!

1. Chestnut

For example (let's take MyBatis as an example):

One thing we have learned from FactoryBean above is that MyBatis in Spring can create and return dynamic proxies through FactoryBean, but we all know an element necessary to use jdk dynamic proxies: interfaces, because jdk dynamic proxies are based on interfaces!

Where do these interfaces come from? To know that Spring will not scan the interface, so at this time we need our custom scanner, we use a custom scanner to scan the interface, and then modify the BeanDefinition to forcibly specify as the FactoryBean type of bean, pass in our interface, and then add BeanDefinition to the bean factory, at this time we need a necessary element interface!

The custom scanner combines FactoryBean III and ImportBeanDefinitionRegistrar1. Call timing

ImportBeanDefinitionRegistrar is also an important part of the life cycle of Spring. Last week, we learned that when Spring executes BeanFactoryPostProcessor, it will implement a post processor built into the execution system-ConfigurationClassPostProcessor. Its function is to scan the classes under the specified path of the project and convert them to the corresponding BeanDefinition! But it's not the only one!

In addition to scanning the classes under the specified package, it also has the ability to parse @ Import annotations. ImportBeanDefinitionRegistrar is a special class in @ Import, which is automatically called back by Spring to the internal registerBeanDefinitions () method!

So it can be seen that the timing of its call is after ConfigurationClassPostProcessor and before all other BeanFactoryPostProcessor!

two。 Callback method and its significance

As we mentioned above, he will call back the registerBeanDefinitions () method, so what's the point? BeanDefinitionRegistryPostProcessor can do similar things if only callbacks can be made. What's so special about it? Let's take a look at its method signature!

Image-20200914224036880

Let's focus on the first parameter, which will encapsulate all the meta-information of the class annotated with @ Import into the AnnotationMetadata class and bring it back when it is called back.

So what's the point of taking it back? For example, still take MyBatis as an example!

Let's imagine the following, as we said above, we can convert each interface to FactoryBean through a custom scanner and give it to Spring to manage, but which package of classes do we want to scan?

Anyone who has used Spring to integrate MyBatis should know that we usually mark an annotation @ MapperScan on the startup class to specify the package path of the Mapper interface, and its purpose is to pass the scanning path to the registerBeanDefinitions method to complete the scan!

Image- 20200914225321751 IV, BeanDefinitionRegistryPostProcessor1. Concept

Although this BeanDefinitionRegistryPostProcessor last week review, I have done a lot of source level explanation! But I still want to talk about it briefly today!

In last week's study, we know that BeanDefinitionRegistryPostProcessor is a subclass of BeanFactoryPostProcessor. What's the difference between them?

We need to know that BeanFactoryPostProcessor can only modify the existing BeanDefinition, but there is no way to add or delete, but BeanDefinitionRegistryPostProcessor is different. It extends the parent class to provide added and deleted API, through which we can add and delete the BeanDefinition of the bean factory!

two。 For instance

We still take MyBatis as an example!

We now convert the interface to a bd through a custom scanner, but how do we add the Bd we scanned to the Spring factory? Use this BeanDefinitionRegistryPostProcessor to register the bean definition!

BeanDefinitionRegistryPostProcessor 5. How does MyBatis extend Spring? 1. Extension step (initialization step)

I believe that through the explanation of the key points above, you should have a similar concept in mind now! The way MyBatis extends Spring is roughly as follows:

First of all, we need to mark an annotation MapperScan in the configuration class and pass in the package path where the Mapper interface is located!

MapperScan will inject a MapperScannerRegistrar class into Spring through the @ Import annotation, which is of type ImportBeanDefinitionRegistrar and will be automatically called back to the registerBeanDefinitions method by Spring!

MapperScannerRegistrar's registerBeanDefinitions method builds a BeanDefinition of type MapperScannerConfigurer, which is of type BeanDefinitionRegistryPostProcessor! Then register into the Spring container!

The Spring lifecycle automatically calls back the postProcessBeanDefinitionRegistry method of MapperScannerConfigurer!

Inside the postProcessBeanDefinitionRegistry method, a custom scanner ClassPathMapperScanner is created, which scans all interfaces under your incoming package path and converts them to BeanDefinition!

After getting all the BeanDefinition of the specified interface, iterate through all the BeanDefinition, and then change his BeanClass to the MapperFactoryBean class, which is of type FactoryBean!

After setting up the BeanClass, pass in the interface represented by the BeanDefinition through the definition.getPropertyValues (). Add () method!

After setting up all the BeanDefinition through steps 6 and 7, all register with the bean factory! These FactoryBean are managed by BeanFactory, and lifecycle management!

Note that these classes are not instantiated at this time, what is instantiated is the FactoryBean class you passed in, and the real class has not been instantiated yet!

two。 Extension step (instantiation step) when using or getting these bean, Spring will first get the type of interface you want to use! Compare all the bean in the current container one by one, and return directly when there is a match! However, because the Mapper interface has not been instantiated yet! So I can't find it, so when I traverse to FactoryBean, the getObjectType method is called to compare the return value with the type of interface you want to use! When the return type of FactoryBean matches, Spring calls the getObject method of FactoryBean to create the object! In the process of creation, do jdk dynamic proxy through the interface passed in before, and complete the agent logic of MyBatis! After the object is created, it is judged by the return value of the isSingleton method that if it is a singleton object, the object is cached! And return!

So far, we have completed the whole process of integrating Spring with MyBatis!

3. Focus on the source code 1) Custom Scanner

How do you customize the scanner within MyBatis? And can also break the original scanning process of Spring, scan the interface into the project!

Image-20200915215932029

The whole code is roughly divided into two parts:

There is no doubt that he created Mybatis's own scanner, which is a subclass of ClassPathBeanDefinitionScanner, which is one of the extension points provided by Spring, based on which we can extend any class to bd, which, of course, needs to conform to our preset rules! What are the preset rules? We can see that there seems to be a registration operation in the first red box of my circle. What is the registration?

Image-20200915220235102

Normally, the judgment is for true, so here is an added logic, where is it?

Image-20200915220432302

It is added to a collection! So far, at least we know, here will add a filter to the collection, as for what is the use, we will talk about later, you remember here!

Let's look at the second red box and start the scan operation! I will not paste the specific code inside, he will call the scanning logic of the parent class, we will directly see how the parent class does it!

Image-20200915220818278

How do you convert the package path to the corresponding bd here?

Image-20200915221123343

With such a long logic, we focus on two judgments:

The first judgment will determine whether the class is filtered and whether it should be converted to BeanDefinition. Remember the filter we just registered? A filter is added to the collection, and this is where it is used!

Image-20200915221801594

Because of the definition of that filter, it must be returned as trueactum here, so we judged it first! A category is converted to BeanDefinition

The second judgment is to call the isCandidateComponent method of the subclass. here is to determine whether a class needs to be added to the collection and returned. We know that Spring will not manage an interface class for us, but the Mapper class happens to be an interface, so MyBatis has to rewrite the original logic to make it support scanning the interface and convert it to bd. Let's take a look at the logic inside! Image-20200915221458473

Because the Mapper class of MyBatis is an interface, it will be returned as true! So we are the second to judge that the BeanDefinition of an interface is added to the collection! And return!

At this point, we probably know how the scanner works! Let's take a look at what we did after scanning the interface.

2) create process image-20200915222512900 through BeanDefinition operation

It iterates through all scanned interfaces bd, passing a value to the constructor of each bd, which is the fully qualified name of the interface represented by the current bd!

When introducing the MyBatis extension FactoryBean above, it said! It creates dynamic proxies through jdk, but where does the interface come from? Is through

Definition.getConstructorArgumentValues () addGenericArgumentValue (beanClassName)

Injected into it! We all know that Spring creates objects based on definition, so we can inject the values we want through definition, and its common usage is similar to the following:

Image-20200915223229818

It is the constructor that injects the value of an interface in MyBatis!

Image-20200915223354790

Forcibly convert the interface type to FactoryBean type!

To delay initialization, he uses the jdk dynamic proxy to return an object! In order to complete the function of MyBatis!

After reading the above, do you have any further understanding of how to understand MyBatis's extended implementation of Spring source code in principle? If you want to know more knowledge or related content, please follow the industry information channel, thank you for your support.

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Internet Technology

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report