【mybatis源码分析】mybatis dao代理对象的注入与使用底层流程

疑问

在我们使用mybatis时需要注入dao到service层,如下代码:


那么我明明没有实现dao接口,框架到底是怎么实现的注入的实现类呢?
调试了一下,发现原来是注入了MapperProxy类,很明显是使用了动态代理

注意:本章需要读者对spring bean生命周期和动态代理知识非常熟练

参考:

主要分为3大步:

  1. @MapperScan注解扫描dao过程

  2. @Autowired注解注入dao的过程

  3. dao的使用过程

一、@MapperScan注解扫描dao过程

1、springboot项目启动时,初始化spring容器会扫描注解,发现了@MapperScan注解。

2、因为@MapperScan注解内部包含@Import注解,所以开始执行注册MapperScannerRegistrar类


3、ImportBeanDefinitionRegistrar类实现了ImportBeanDefinitionRegistrar接口,所以会执行registerBeanDefinitions方法去手动注册BeanDefinition。


4、上图代码中只注册了一个MapperScannerConfigurer类,又因为这个类实现了BeanDefinitionRegistryPostProcessor接口,所以又开始执行postProcessBeanDefinitionRegistry方法

5、这个类主要是创建了一个ClassPathMapperScanner类,用于扫描@MapperScan注解配置的包(扫描项目中的Dao接口并注册进spring容器)

6、ClassPathMapperScanner类的doScan方法分成两部分。

第一部分是正常的spring的注册beanDefinition。例如:beanName是UserDao,beanClass是com.example.demo.UserDao

第二部分是mybatis修改beanDefinition:例如:beanName是UserDao,beanClass改成org.apache.ibatis.binding.MapperFactoryBean。

为了让spring创建bean的时候创建MapperFactoryBean类型的对象,方便下一步通过@Autowired注解注入UserDao对象。
 

 

二、通过@Autowired注入dao的过程

现在就到了spring的属性注入阶段,例如:service类需要注入dao了。spring会根据dao beanDefinition生产一个名为UserDao,类型是MapperProxy的bean。

1、在生产的过程中,由于MapperFactoryBean实现了FactoryBean接口(spring的扩展接口),所以会调用此类的getObject()方法返回实例对象。

(正常是由spring反射创建的对象,而实现了FactoryBean接口的bean,就由用户自己创建)

FactoryBean接口的参考:https://blog.csdn.net/sumengnan/article/details/113634063

2、此方法最终通过mapperRegistry对象的getMapper方法获取到MapperProxyFactory工厂

3、再通过MapperProxyFactory工厂,创建jdk动态代理对象,把MapperProxy当作处理器

4、因为MapperProxy类实现了InvocationHandler接口,所以有invoke方法可以作为处理器使用。

三、dao的使用过程

1、当我们调用UserDao时,实际上调用的是MapperProxy的invoke方法。

2、一般会走cachedInvoker方法。先从缓存中查询MapperMethodInvoker如果不存在则创建一个PlainMethodInvoker的类(构造方法是MapperMethod类)

3、PlainMethodInvoker的类会被放入methodCache缓存,并执行invoke方法

3、继续调用到MapperMethod类的execute方法。(这个类是真正用于执行数据库操作的类)

4、例如我的执行sql是select语句。在execute方法中判断为SELECT,最终通过sqlSession类执行的数据库操作。

猜你喜欢

转载自blog.csdn.net/sumengnan/article/details/113953507