zoukankan      html  css  js  c++  java
  • 聊聊、手写Mybatis SpringBoot Starter

    导航: 

    聊聊、Mybatis API 

    聊聊、Mybatis XML

    聊聊、Mybatis集成Spring XML 方式

    聊聊、Mybatis集成Spring 注解方式 

    聊聊、手写Mybatis XML配置方式  

    聊聊、手写Mybatis 注解配置方式  

    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。

  • 相关阅读:
    在windows系统和linux系统中查询IP地址命令的不同
    Linux --忘记root密码/su: Authentication failure
    Spring+quartz集群解决多服务器部署定时器重复执行的问题
    spring定时任务scheduler集群环境下指定运行服务器防止多服务器多次执行
    跨库数据表的运算
    AspectJ 切面注解中五种通知注解:@Before、@After、@AfterRunning、@AfterThrowing、@Around
    JUnit4 中@AfterClass @BeforeClass @after @before的区别对比
    Java后端的学习之Spring基础
    MySQL 5.7默认ONLY_FULL_GROUP_BY语义介绍
    【可靠性】Mysql 5.7 降低了半同步复制-数据丢失的风险
  • 原文地址:https://www.cnblogs.com/xums/p/12671689.html
Copyright © 2011-2022 走看看