導航:
SpringBoot 現在應該很多公司都用到了,在它出現之前呢,我們用 Spring 要寫很多的配置文件,各種各樣的 XML 文件。而且我們在引入 Spring 的時候,會加入很多的 jar 包,很多時候會由於版本不匹配問題,而導致啟動失敗。在配置好文件和正確引入各種 jar 以后,我們需要將項目打包成 war,然后放到 web 服務器。
SpringBoot 是發展趨勢,那么它有哪些特性呢?或者它能幫我們做什么呢?
SpringBoot特性
1.能夠快速的創建項目,利用 Spring initializr 快速創建項目,平時我們用到的開發工具也集成了這些插件,所以非常方便
2.通過 jar 來啟動項目,也就是內嵌的 web 服務器
3.通過 starter 來管理依賴,解決版本不匹配問題,零配置文件
4.可以檢查程序健康狀況,度量標准
創建 mybatis-spring-boot-starter
關於 starter 的命名,如果是我們自己創建 starter,一般是 項目名稱-spring-boot-starter,這個和官網的 starter 不一樣,官網的是將項目名稱放最后,例如:spring-boot-starter-web
我創建的是 mybatis,所以是 mybatis-spring-boot-starter


自己寫 SpringBoot Starter 必須要知道 EnableAutoConfiguration,SpringBoot 自動配置就是通過它來實現。SpringBoot 在啟動的時候會去 META-INF 包下面讀取 spring.factories 文件。
例如:mybatis-spring-boot-starter

spring.factories:
org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.rockcode.mybatis.configurations.MybatisAutoConfiguration
這里告訴 SpringBoot 我的自動配置類是 MybatisAutoConfiguration
MybatisAutoConfiguration
@Configuration
@EnableConfigurationProperties(MybatisProperties.class)
public class MybatisAutoConfiguration {
@Autowired
private MybatisProperties mybatisProperties;
@Bean
public SqlSessionFactoryBean sqlSessionFactoryBean(DataSource dataSource){
SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
sqlSessionFactoryBean.setDataSource(dataSource);
return sqlSessionFactoryBean;
}
@Bean
public DataSource dataSource(){
DruidDataSource driverManagerDataSource = new DruidDataSource();
driverManagerDataSource.setDriverClassName(mybatisProperties.getDriver());
driverManagerDataSource.setUrl(mybatisProperties.getUrl());
driverManagerDataSource.setUsername(mybatisProperties.getUsername());
driverManagerDataSource.setPassword(mybatisProperties.getPassword());
return driverManagerDataSource;
}
}
MybatisProperties
@ConfigurationProperties(prefix = "mybatis.database")
public class MybatisProperties {
private String driver;
private String url;
private String username;
private String password;
// getter setter 方法忽略
}
上面有兩個 SpringBoot 知識點,@ConfigurationProperties(prefix = "mybatis.database"),@EnableConfigurationProperties(MybatisProperties.class),這兩個在 SpringBoot 用的非常多,它們的好處是,你可以直接
@Autowired
private MybatisProperties mybatisProperties;
這樣你就可以獲取到所有的屬性值,也就是生成了 Bean 對象。例如我想獲取 url,那么直接 mybatisProperties.getUrl() 就行。這兩個類會在后面的 SpringBoot 源碼系列 文章里面聊。
其他的類,跟《聊聊、手寫Mybatis 注解配置方式》里面的內容一樣。
AccountMapperFactoryBean
public class AccountMapperFactoryBean extends SqlSessionDaoSupport implements FactoryBean {
private Class mapperInterface;
public void setMapperInterface(Class mapperInterface) {
this.mapperInterface = mapperInterface;
}
@Autowired
public void setSqlSessionFactory(SqlSessionFactory sqlSessionFactory) {
super.setSqlSessionFactory(sqlSessionFactory);
}
@Override
protected void checkDaoConfig() {
super.checkDaoConfig();
notNull(this.mapperInterface, "Property 'mapperInterface' is required");
Configuration configuration = getSqlSession().getConfiguration();
configuration.addMapper(this.mapperInterface);
}
@Override
public Object getObject() throws Exception {
return getSqlSession().getMapper(this.mapperInterface);
}
@Override
public Class<?> getObjectType() {
return this.mapperInterface;
}
}
AccountMapperScan
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
@Import(AccountImportBeanDefinitionRegistrar.class)
public @interface AccountMapperScan {
String[] value() default {};
String[] basePackages() default {};
}
AccountImportBeanDefinitionRegistrar
public class AccountImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
@Override
public void registerBeanDefinitions(AnnotationMetadata annotationMetadata, BeanDefinitionRegistry beanDefinitionRegistry) {
Map<String, Object> annotationAttributes = annotationMetadata.getAnnotationAttributes(AccountMapperScan.class.getName());
String[] value = (String[]) annotationAttributes.get("value");
String packages = value[0];
AccountClassPathMapperScanner myClassPathBeanDefinitionScanner = new AccountClassPathMapperScanner(beanDefinitionRegistry);
myClassPathBeanDefinitionScanner.registerFilters();
myClassPathBeanDefinitionScanner.scan(packages);
}
}
AccountClassPathMapperScanner
public class AccountClassPathMapperScanner extends ClassPathBeanDefinitionScanner {
public AccountClassPathMapperScanner(BeanDefinitionRegistry registry) {
super(registry, false);
}
public void registerFilters() {
addIncludeFilter(new TypeFilter() {
@Override
public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException {
return true;
}
});
}
@Override
public Set<BeanDefinitionHolder> doScan(String... basePackages) {
Set<BeanDefinitionHolder> beanDefinitionHolders = super.doScan(basePackages);
GenericBeanDefinition definition;
for (BeanDefinitionHolder holder : beanDefinitionHolders) {
definition = (GenericBeanDefinition) holder.getBeanDefinition();
String beanClassName = definition.getBeanClassName();
try {
Class<?> clazz = Class.forName(beanClassName);
definition.setBeanClass(AccountMapperFactoryBean.class);
definition.getPropertyValues().add("mapperInterface", clazz);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
return beanDefinitionHolders;
}
@Override
protected boolean isCandidateComponent(AnnotatedBeanDefinition beanDefinition) {
return beanDefinition.getMetadata().isInterface() && beanDefinition.getMetadata().isIndependent();
}
}
application.properties
mybatis.database.driver = com.mysql.jdbc.Driver
mybatis.database.url = jdbc:mysql://127.0.0.1:3306/test?useSSL=false
mybatis.database.username = root
mybatis.database.password = root
pom.xml
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.5.RELEASE</version>
<relativePath/>
</parent>
<groupId>com.rockcode</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>mybatis-spring-boot-starter</name>
<description>mybatis-spring-boot-starter</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.1.6.RELEASE</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>2.0.2</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.4</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.30</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.0.31</version>
</dependency>
</dependencies>
上面就是所有的代碼和配置了,然后打包成 mybatis-spring-boot-starter-0.0.1-SNAPSHOT.jar。
在其他的項目中,我們只需要引用就可以。
<dependency>
<groupId>com.rockcode</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
好了,Mybatis 系列文章就到這里結束了。源碼地址:https://github.com/xumiaoshun/mybatis-spring-boot-starter.git。
