用过springboot的确定很熟悉,它其中有个重要的特性,就是自动配置(平时习惯的一些设置的配置做为默认配置)。springboot提倡无XML配置文件的理念,使用springboot生成的应用彻底不会生成任何配置代码与XML配置文件。下面先看一个springboot集成mybatis的例子。
第一步: 引入pom文件java
<dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>2.0.1</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.47</version> </dependency>
第二步: 由于我使用的xml配置文件去使用mybatis,在application.properties文件加入以下配置:mysql
#指定mapper文件位置 mybatis.mapper-locations=classpath:mapper/*.xml #数据源信息 spring.datasource.url=jdbc:mysql://127.0.0.1:3306/zplxjj?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=GMT%2B8 spring.datasource.username=root spring.datasource.password=123456 spring.datasource.driver-class-name=com.mysql.jdbc.Driver
第三步: 加入实体类、dao、mapper文件
第四步:启动类上面加入注解spring
@SpringBootApplication @MapperScan("com.stone.zplxjj.dao") public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } }
第五步:至此,配置完成,只须要写个单侧,springboot已经完美集成mybatissql
@RunWith(SpringRunner.class) @SpringBootTest public class ApplicationTests { @Autowired UserMapper userMapper; @Test public void testMybatis() { System.out.println(userMapper.selectByPrimaryKey(1L)); } }
经过上面的例子,咱们发现集成mybatis特别简单,那些繁琐的类的注入都没有写,只须要加入数据库的一些配置便可,那这其中@EnableAutoConfiguration功不可没。@EnableAutoConfiguration 注解已经在@SpringBootApplication里面了数据库
@Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited @SpringBootConfiguration @EnableAutoConfiguration @ComponentScan( excludeFilters = {@Filter( type = FilterType.CUSTOM, classes = {TypeExcludeFilter.class} ), @Filter( type = FilterType.CUSTOM, classes = {AutoConfigurationExcludeFilter.class} )} ) public @interface SpringBootApplication { @AliasFor( annotation = EnableAutoConfiguration.class ) Class<?>[] exclude() default {}; @AliasFor( annotation = EnableAutoConfiguration.class ) String[] excludeName() default {}; @AliasFor( annotation = ComponentScan.class, attribute = "basePackages" ) String[] scanBasePackages() default {}; @AliasFor( annotation = ComponentScan.class, attribute = "basePackageClasses" ) Class<?>[] scanBasePackageClasses() default {}; }
咱们看到@EnableAutoConfiguration结构以下:springboot
@Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited @AutoConfigurationPackage @Import({AutoConfigurationImportSelector.class}) public @interface EnableAutoConfiguration { String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration"; Class<?>[] exclude() default {}; String[] excludeName() default {}; }
这其中起做用的一个重要注解@Import,这个Spring提供的一个注解,能够导入配置类或者Bean到当前类中,咱们进入到AutoConfigurationImportSelector类中查看,方法太长,截取核心的两个方法:微信
public String[] selectImports(AnnotationMetadata annotationMetadata) { if (!this.isEnabled(annotationMetadata)) { return NO_IMPORTS; } else { AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader.loadMetadata(this.beanClassLoader); AutoConfigurationImportSelector.AutoConfigurationEntry autoConfigurationEntry = this.getAutoConfigurationEntry(autoConfigurationMetadata, annotationMetadata); return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations()); } } protected AutoConfigurationImportSelector.AutoConfigurationEntry getAutoConfigurationEntry(AutoConfigurationMetadata autoConfigurationMetadata, AnnotationMetadata annotationMetadata) { if (!this.isEnabled(annotationMetadata)) { return EMPTY_ENTRY; } else { AnnotationAttributes attributes = this.getAttributes(annotationMetadata); List<String> configurations = this.getCandidateConfigurations(annotationMetadata, attributes); configurations = this.removeDuplicates(configurations); Set<String> exclusions = this.getExclusions(annotationMetadata, attributes); this.checkExcludedClasses(configurations, exclusions); configurations.removeAll(exclusions); configurations = this.filter(configurations, autoConfigurationMetadata); this.fireAutoConfigurationImportEvents(configurations, exclusions); return new AutoConfigurationImportSelector.AutoConfigurationEntry(configurations, exclusions); } }
经过项目启动后,打上注解,能够看到MybatisAutoConfiguration引入了进来
而MybatisAutoConfiguration能引入进来,实际上是在mybatis-spring-boot-autoconfigure-2.0.1.jar包里面的spring.factories指定的,经过调用SpringFactoriesLoader.loadFactoryNames()来扫描加载含有META-INF/spring.factories文件的jar包,从而标识哪些自动配置的类mybatis
# Auto Configure org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ org.mybatis.spring.boot.autoconfigure.MybatisAutoConfiguration
@Conditional 的做用,能够根据条件去加载特定的bean,原理这边不作探讨,springboot基于此实现了几个注解,比较方便的实现条件加载类
@ConditionalOnBean:Spring容器中是否存在对应的实例
@ConditionalOnMissingBean:Spring容器中是否缺乏对应的实例
经过查看MybatisAutoConfiguration中的SqlSessionFactory的写法app
@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())); } this.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()); } return factory.getObject(); }
经过上面分析mybatis如何集成springboot,知道了springboot入口在哪里以及如何实现的自动配置,这里只是简单的作了介绍,其中的一些源码和细节就没有分析了,我相信,入口知道了,接下来就好抠细节了。ide
本人也开通了微信公众号:stonezplxjj和我的博客:http://www.zplxjj.com,更多文章欢迎关注公众号: