数据源自动配置
spring.factories中找到数据源的配置类:
Mybatis自动配置源码分析
1、springboot项目最核心的就是自动加载配置,该功能则依赖的是一个注解 @SpringBootApplication中的@EnableAutoConfiguration
2、EnableAutoConfiguration主要是通过AutoConfigurationImportSelector类来加载
以mybatis为例,*selector(所有的selector)通过反射加载spring.factories中指定的java类,也就是加载 MybatisAutoConfiguration类(该类有Configuration注解,属于配置类)
3、MybatisAutoConfiguration:
①类中有个MybatisProperties类,该类对应的是mybatis的配置文件
②类中有个sqlSessionFactory方法,作用是创建SqlSessionFactory类、Configuration类 (mybatis最主要的类,保存着与mybatis相关的东西)
③SelSessionTemplate,作用是与mapperProoxy代理类有关
sqlSessionFactory主要是通过创建了一个SqlSessionFactoryBean,这个类实现了FactoryBean接 口,所以在Spring容器就会注入这个类中定义的getObject方法返回的对象。
看一下getObject()方法做了什么?
这个已经很明显了,实际上就是调用了MyBatis的初始化流程 现在已经得到了SqlSessionFactory了,接下来就是如何扫描到相关的Mapper接口了。
这个需要看这个注解
@MapperScan(basePackages = “com.mybatis.mapper”)
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
@Import(MapperScannerRegistrar.class)
@Repeatable(MapperScans.class)
public @interface MapperScan
通过@Import的方式会扫描到MapperScannerRegistrar类。 MapperScannerRegistrar实现了ImportBeanDefinitionRegistrar接口,那么在spring实例化之前 就会调用到registerBeanDefinitions方法
public class MapperScannerRegistrar implements
ImportBeanDefinitionRegistrar, ResourceLoaderAware
@Override
public void registerBeanDefinitions(AnnotationMetadata
importingClassMetadata, BeanDefinitionRegistry registry) {
//拿到MapperScan注解,并解析注解中定义的属性封装成AnnotationAttributes对象
AnnotationAttributes mapperScanAttrs = AnnotationAttributes
.fromMap(importingClassMetadata.getAnnotationAttributes(MapperScan.class.get
Name()));
if (mapperScanAttrs != null) {
registerBeanDefinitions(importingClassMetadata, mapperScanAttrs,
registry,
generateBaseBeanName(importingClassMetadata, 0));
}
}
//........
MapperScannerConfigurer实现了BeanDefinitionRegistryPostProcessor接口,所以接着又会扫 描并调用到postProcessBeanDefinitionRegistry方法。
修改了mapper的beanClass类型为MapperFactoryBea
上述几步主要是完成通过 @MapperScan(basePackages = “com.mybatis.mapper”)这个定义,扫描指定包下的 mapper接口,然后设置每个mapper接口的beanClass属性为MapperFactoryBean类型并加入 到spring的bean容器中。
MapperFactoryBean实现了FactoryBean接口,所以当spring从待实例化的bean容器中遍历到这 个bean并开始执行实例化时返回的对象实际上是getObject方法中返回的对象。
public class MapperFactoryBean<T> extends SqlSessionDaoSupport implements
FactoryBean<T>
最后看一下MapperFactoryBean的getObject方法,实际上返回的就是mybatis中通过getMapper 拿到的对象,熟悉mybatis源码的就应该清楚,这个就是mybatis通过动态代理生成的mapper接 口实现类’
@Override
public T getObject() throws Exception {
return getSqlSession().getMapper(this.mapperInterface);
}
到此,mapper接口现在也通过动态代理生成了实现类,并且注入到spring的bean容器中了,之后 使用者就可以通过@Autowired或者getBean等方式,从spring容器中获取到了