In mybatis, I often use @ MapperScan annotation. Let's see how it is integrated into spring. First, when we enter MapperScan, we will see @ import (mapperscannerregister. Class)
When we open mappercannerregister, we will see that the importbeandefinitionregister interface is implemented. This interface will call the registerBeanDefinitions method that implements the importbeandefinitionregister interface when spring loads and starts to parse the import annotation
Open the registerBeanDefinitions method and you will see that mappercannerconfigurer Class generated beanefinitionBuilder
From the above figure, we can see that mappercannerconfigurer is directly registered as beanDefinitionBuilder, while mappercannerconfigurer What role does class play? Let's go into this class and see what he did
If you know about spring, you should be familiar with BeanDefinitionRegistryPostProcessor, InitializingBean, ApplicationContextAware and BeanNameAware. When scanning and loading bean definitions during spring loading, call the postProcessBeanDefinitionRegistry method that implements the BeanDefinitionRegistryPostProcessor interface
A new ClassPathMapperScanner class is created, and the BeanDefinitionRegistry register is passed in as the constructor parameter. Then the scan method is used to scan the mapper interface class of the specified package. We enter the dosan method in the scan method, and pay attention to the way to enter the dosan method to enter the next surface of the mybatis-spring package, and when we enter the doScan method, we should pay attention to it. Mybatis rewrites the doscan method of ClassPathBeanDefinitionScanner, so it should enter the method of the second image
The spring method of calling the parent class in the annotation 1 in the above figure scans the beanDefinition collection of the mapper interface, and then annotate the beanDefinition packaged by factoryBean by tagging the 2 method. Then, the getObject method of factoryBean is invoked when instantiating bean, and is enhanced in the getObject method, that is to create dynamic proxy.
Enter definition Parameters of setbeanclass (this. Maperfactorybeanclass) code snippet maperfactorybeanclass take a look at this factory bean
public class MapperFactoryBean<T> extends SqlSessionDaoSupport implements FactoryBean<T> {//This class implements the factoryBean interface private Class<T> mapperInterface;//Store the parameters of the actual mapper interface private boolean addToConfig = true; public MapperFactoryBean() { // intentionally empty } public MapperFactoryBean(Class<T> mapperInterface) {//This method will be used for parameter injection in subsequent spring getbean s this.mapperInterface = mapperInterface; }
Next, we find the getObject method of factoryBean
@Override public T getObject() throws Exception { return getSqlSession().getMapper(this.mapperInterface);//From here, you can find the method of generating JDK dynamic proxy }
Finally, the following code will be called to generate the dynamic proxy class
@Override public <T> T getMapper(Class<T> type, SqlSession sqlSession) { // TODO here is replaced by mybatismappperproxyfactory instead of MapperProxyFactory final MybatisMapperProxyFactory<T> mapperProxyFactory = (MybatisMapperProxyFactory<T>) knownMappers.get(type); if (mapperProxyFactory == null) { throw new BindingException("Type " + type + " is not known to the MybatisPlusMapperRegistry."); } try { return mapperProxyFactory.newInstance(sqlSession);//From here, you can see the code that generates the dynamic agent. If you are interested, you can follow in and have a look } catch (Exception e) { throw new BindingException("Error getting mapper instance. Cause: " + e, e); } }
The core process of integrating spring with mybatis has been sorted out. Here is a flow chart for your reference