参考 https://blog.csdn.net/weixin_39854681/article/details/110859474
springboot 集成 mybatis 1、配置 maven 依赖2、application.yml配置文件org.mybatis.spring.boot mybatis-spring-boot-starter
###服务器配置 server: port: 9001 spring: application: name: user ###druid数据源配置 datasource: name: dataSource type: com.alibaba.druid.pool.DruidDataSource driver-class-name: com.mysql.jdbc.Driver url: jdbc:mysql://127.0.0.1:3306/imalvisc?useSSL=false username: root password: imalvisc druid: initial-size: 5 ................. ###mybatis数据源配置 mybatis: type-aliases-package: com.imalvisc.spring.mybatis.model configuration: map-underscore-to-camel-case: true3、启动类
package com.imalvisc.spring.mybatis; import com.imalvisc.spring.mybatis.mapper.UserInfoMapper; import org.mybatis.spring.annotation.MapperScan; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.ConfigurableApplicationContext; @SpringBootApplication @MapperScan(basePackages = {"com.imalvisc.spring.mybatis.mapper"}) public class Application { public static void main(String[] args) { ConfigurableApplicationContext applicationContext = SpringApplication.run(Application.class, args); UserInfoMapper userInfoMapper = applicationContext.getBean(UserInfoMapper.class); System.out.println(userInfoMapper.selectAll()); } }
以上就已经将 springboot 集成 mybatis 环境搭建完成
原理分析项目中引入了 mybatis-spring-boot-starter 依赖,所以间接引入了 mybatis-spring-boot-autoconfigure ,在 mybatis-spring-boot-autoconfigure 的类路径下,看到 meta-INF 目录下有一个 spring.factories 文件,文件内容是个类似键值对的配置,key 是 EnableAutoConfiguration ,值是 mybatis 的配置类如下
注意: springboot 项目启动时,会扫描项目本身及依赖的【所有 jar 包】类路径下的 meta-INF 目录的 spring.factories 文件,再根据文件内容中的【全限定类名】找到并加载执行该类,这就是 springboot 自动配置的真谛。
上述键值对的值中一个类是 MybatisLanguageDriverAutoConfiguration
注解含义
// 相当于@org.springframework.context.annotation.Configuration // 当前classpath路径下面是否存在 SqlSessionFactory.class, SqlSessionFactoryBean.class,存在则 // 进行将当前配置装载到spring容器中 @ConditionalOnClass({ SqlSessionFactory.class, SqlSessionFactoryBean.class }) // 相当于 beanFactory.getBeanByType(javax.sql.DataSource.class) @ConditionalOnBean(DataSource.class) // 让用了 @ConfigurationProperties 注解的类生效并将该类注入到 IOC 容器中,交由 IOC 容器进行管理 // MybatisProperties 是 yml 中 mybatis 配置属性的实体映射,该类用了 @ConfigurationProperties @EnableConfigurationProperties(MybatisProperties.class) // 顺序在DataSourceAutoConfiguration.class之后 @AutoConfigureAfter(DataSourceAutoConfiguration.class)
其他 Conditional 注解
@Conditional(TestCondition.class) 这句代码可以标注在类上面,表示该类下面的所有 @Bean 都会启用配置,也可以标注在方法上面,只是对该方法启用配置。 @ConditionalOnBean(仅仅在当前上下文中存在某个对象时,才会实例化一个 Bean) @ConditionalOnClass(某个 class 位于类路径上,才会实例化一个 Bean) @ConditionalOnSingleCandidate(DataSource.class) IOC 容器中只有一个指定的候选对象才起作用 @ConditionalOnexpression(当表达式为true的时候,才会实例化一个 Bean) @ConditionalOnMissingBean(仅仅在当前上下文中不存在某个对象时,才会实例化一个 Bean) @ConditionalOnMissingClass(某个 class 类路径上不存在的时候,才会实例化一个 Bean) @ConditionalOnNotWebApplication(不是web应用)
这是一个 Configuration 类,@AutoConfigureAfter(DataSourceAutoConfiguration.class) 代表在DataSourceAutoConfiguration 类加载完后再加载,因为 mybatis 要依赖数据源配置,要在数据源配置完成后才进行 mybatis 配置。在 MybatisAutoConfiguration 类中,配置了 SqlSessionFactory类,所在到这里 mybatis 的环境就已经生效了。
@Bean @ConditionalOnMissingBean public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception { SqlSessionFactoryBean factory = new SqlSessionFactoryBean(); factory.setDataSource(dataSource); factory.setVfs(SpringBootVFS.class); if (StringUtils.hasText(this.properties.getConfigLocation())) { factory.setConfigLocation(this.resourceLoader.getResource(this.properties.getConfigLocation())); } applyConfiguration(factory); if (this.properties.getConfigurationProperties() != null) { factory.setConfigurationProperties(this.properties.getConfigurationProperties()); } if (!ObjectUtils.isEmpty(this.interceptors)) { factory.setPlugins(this.interceptors); } if (this.databaseIdProvider != null) { factory.setDatabaseIdProvider(this.databaseIdProvider); } if (StringUtils.hasLength(this.properties.getTypeAliasesPackage())) { factory.setTypeAliasesPackage(this.properties.getTypeAliasesPackage()); } if (this.properties.getTypeAliasesSuperType() != null) { factory.setTypeAliasesSuperType(this.properties.getTypeAliasesSuperType()); } if (StringUtils.hasLength(this.properties.getTypeHandlersPackage())) { factory.setTypeHandlersPackage(this.properties.getTypeHandlersPackage()); } if (!ObjectUtils.isEmpty(this.properties.resolveMapperLocations())) { factory.setMapperLocations(this.properties.resolveMapperLocations()); }
SqlSessionFactory 配置完成后,剩下的就是扫描 mapper 接口并生成代理类存放到 IOC 容器中,这样就可以依赖注入 Mapper 了。
在 Application 启动类中,加上了 @MapperScan(basePackages = {“xxx”}) 注解, MapperScan 注解类上加上另一个注解 @import(MapperScannerRegistrar.class),spring 监测到 @import 注解时会加载其指定的配置类 MapperScannerRegistrar
@Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) @documented @import(MapperScannerRegistrar.class) @Repeatable(MapperScans.class) public @interface MapperScan { }
2.5、查看 MapperScannerRegistrar 发现,其实现了 importBeanDefinitionRegistrar 接口,该接口的作用是 spring 会调用实现该接口的 registerBeanDefinitions 方法,传入 Annotationmetadata 和BeanDefinitionRegistry 两个参数,Annotationmetadata 的作用是封装了加上@import注解的注解的属性(这里就是MapperScan的basePackages = {“xxx”}),
总结说明:就是 @MapperScan 注解加上了 @import 注解, Annotationmetadata 封装了@MapperScan 注解的 basePackages 属性的值。
2.6、MapperScannerRegistrar 的 registerBeanDefinitions 方法中,获取了 @MapperScan 注解的属性后,调用了自身的重载 registerBeanDefinitions 方法,重载 registerBeanDefinitions 方法通过调用ClassPathMapperScanner 的 doScan 方法就完成了 Mapper 的扫描并生产动态代理加入到 spring 容器中。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)