数据源自动配置

spring.factories中找到数据源的配置类:

Mybatis自动配置源码分析

1、springboot项目最核心的就是自动加载配置,该功能则依赖的是一个注解 @SpringBootApplication中的@EnableAutoConfiguration
2、EnableAutoConfiguration主要是通过AutoConfigurationImportSelector类来加载

以mybatis为例,*selector(所有的selector)通过反射加载spring.factories中指定的java类,也就是加载 MybatisAutoConfiguration类(该类有Configuration注解,属于配置类)

image.png

image.png

3、MybatisAutoConfiguration:
①类中有个MybatisProperties类,该类对应的是mybatis的配置文件
②类中有个sqlSessionFactory方法,作用是创建SqlSessionFactory类、Configuration类 (mybatis最主要的类,保存着与mybatis相关的东西)
③SelSessionTemplate,作用是与mapperProoxy代理类有关

sqlSessionFactory主要是通过创建了一个SqlSessionFactoryBean,这个类实现了FactoryBean接 口,所以在Spring容器就会注入这个类中定义的getObject方法返回的对象。

看一下getObject()方法做了什么?

这个已经很明显了,实际上就是调用了MyBatis的初始化流程 现在已经得到了SqlSessionFactory了,接下来就是如何扫描到相关的Mapper接口了。
这个需要看这个注解

  1. @MapperScan(basePackages = com.mybatis.mapper”)
  2. @Retention(RetentionPolicy.RUNTIME)
  3. @Target(ElementType.TYPE)
  4. @Documented
  5. @Import(MapperScannerRegistrar.class)
  6. @Repeatable(MapperScans.class)
  7. public @interface MapperScan


通过@Import的方式会扫描到MapperScannerRegistrar类。 MapperScannerRegistrar实现了ImportBeanDefinitionRegistrar接口,那么在spring实例化之前 就会调用到registerBeanDefinitions方法

  1. public class MapperScannerRegistrar implements
  2. ImportBeanDefinitionRegistrar, ResourceLoaderAware
  1. @Override
  2. public void registerBeanDefinitions(AnnotationMetadata
  3. importingClassMetadata, BeanDefinitionRegistry registry) {
  4. //拿到MapperScan注解,并解析注解中定义的属性封装成AnnotationAttributes对象
  5. AnnotationAttributes mapperScanAttrs = AnnotationAttributes
  6. .fromMap(importingClassMetadata.getAnnotationAttributes(MapperScan.class.get
  7. Name()));
  8. if (mapperScanAttrs != null) {
  9. registerBeanDefinitions(importingClassMetadata, mapperScanAttrs,
  10. registry,
  11. generateBaseBeanName(importingClassMetadata, 0));
  12. }
  13. }
  14. //........

MapperScannerConfigurer实现了BeanDefinitionRegistryPostProcessor接口,所以接着又会扫 描并调用到postProcessBeanDefinitionRegistry方法。

修改了mapper的beanClass类型为MapperFactoryBea

上述几步主要是完成通过 @MapperScan(basePackages = “com.mybatis.mapper”)这个定义,扫描指定包下的 mapper接口,然后设置每个mapper接口的beanClass属性为MapperFactoryBean类型并加入 到spring的bean容器中。

MapperFactoryBean实现了FactoryBean接口,所以当spring从待实例化的bean容器中遍历到这 个bean并开始执行实例化时返回的对象实际上是getObject方法中返回的对象。

  1. public class MapperFactoryBean<T> extends SqlSessionDaoSupport implements
  2. FactoryBean<T>

最后看一下MapperFactoryBean的getObject方法,实际上返回的就是mybatis中通过getMapper 拿到的对象,熟悉mybatis源码的就应该清楚,这个就是mybatis通过动态代理生成的mapper接 口实现类’

  1. @Override
  2. public T getObject() throws Exception {
  3. return getSqlSession().getMapper(this.mapperInterface);
  4. }

到此,mapper接口现在也通过动态代理生成了实现类,并且注入到spring的bean容器中了,之后 使用者就可以通过@Autowired或者getBean等方式,从spring容器中获取到了