手写模拟实现一个简易Mybatis,支持XML和注解方式查询

本文承接上一文章的小节继续展开Mybatis(调用简图和框架设计思路)+手写模拟mybatis源码分享_喜欢火影的木易杨的博客-CSDN博客

我们结合前面对Mybatis设计的分层结构猜想,参考mybatis源码进行手写,支持通过sqlSession查询数据库,也支持模拟Spring整合扫描@Mapper的注解通过mapper接口直接查询数据库。本小节代码会进行详细讲解,代码在CSDN链接手写简易mybatis-Java文档类资源-CSDN下载。

首先,整体代码的设计思路紧紧围绕下图展开:

手写模拟实现一个简易Mybatis,支持XML和注解方式查询_第1张图片

本项目为了方便运行构建,使用SpringBoot构建。整体代码分层如下:

手写模拟实现一个简易Mybatis,支持XML和注解方式查询_第2张图片

还是从TestMybatis.java展开:

import com.test.mapper.BlogMapper;
import com.test.model.Blog;
import custom.annotation.Mapper;
import custom.annotation.MapperScan;
import custom.io.Resources;
import custom.session.CustomSqlSession;
import custom.session.SqlSessionFactory;
import custom.session.SqlSessionFactoryBuilder;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;

import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import java.util.Properties;

@SpringBootApplication(exclude = { DataSourceAutoConfiguration.class, DataSourceTransactionManagerAutoConfiguration.class })
@ComponentScan(basePackages={"custom","com.test"})
@MapperScan(value="com.test", annotationClass= Mapper.class)
public class TestMybatis {
  public static void main(String[] args) throws IOException {

    ConfigurableApplicationContext context = SpringApplication.run(TestMybatis.class);

    //得到SqlSession
    CustomSqlSession sqlSession = context.getBean(CustomSqlSession.class);

    //通过namesace直接查询
    Blog blog2 = (Blog) sqlSession.selectOne("com.test.model.BlogMapper.selectTestById", 2);
    System.out.println(blog2);

    //mapper接口获取代理类,通过代理类查询
    Blog query = new Blog();
    query.setId(1);
    BlogMapper blogMapper = sqlSession.getMapper(BlogMapper.class);
    Blog blog3 = blogMapper.selectBlog(query);
    System.out.println(blog3);

  }

  @Bean
  public SqlSessionFactory getSqlSessionFactory() throws IOException{
    //解析mybatis-config配置文件
    InputStream is = Resources.getResourceAsStream("mybatis-config.xml");
    Properties properties = new Properties();
    //数据库配置信息
    properties.load(Resources.getResourceAsStream("config.properties"));
    return new SqlSessionFactoryBuilder().build(is, properties);
  }

  @Bean("defaultSqlSession")
  public CustomSqlSession getCustomSqlSession(SqlSessionFactory sqlSessionFactory) throws IOException {
      //得到SqlSession
     return sqlSessionFactory.openSession();
  }

}

这里就使用了SqlSessionFactoryBuilder、sqlSessionFactory、CustomSqlSession

SqlSessionFactoryBuilder主要接收配置流,在build方法中调用XMLConfigBuilder类进行配置文件解析,同时内部还会调用XMLMapperBuilder类进行mapper文件的解析,解析后的信息放在Configuration类当中。在mybatis源码中使用xpath进行解析,而我们自己手写的则使用dom4j进行节点解析。

手写模拟实现一个简易Mybatis,支持XML和注解方式查询_第3张图片

手写模拟实现一个简易Mybatis,支持XML和注解方式查询_第4张图片

手写模拟实现一个简易Mybatis,支持XML和注解方式查询_第5张图片

手写模拟实现一个简易Mybatis,支持XML和注解方式查询_第6张图片

手写模拟实现一个简易Mybatis,支持XML和注解方式查询_第7张图片

手写模拟实现一个简易Mybatis,支持XML和注解方式查询_第8张图片

接下来是获取sqlSession,通过 sqlSessionFactory.openSession()

手写模拟实现一个简易Mybatis,支持XML和注解方式查询_第9张图片

创建一个sqlSession实现类,传入需要的configuration配置信息,以及一个JDBC执行器对象。

手写模拟实现一个简易Mybatis,支持XML和注解方式查询_第10张图片

手写模拟实现一个简易Mybatis,支持XML和注解方式查询_第11张图片

这样就完成了第一个调用简图的调用过程。其它核心代码可下载完整工程运行查看。

接下来是扫描Mapper注解并生成动态代理类的逻辑。核心思路是定义接口,Mapper注解,SelectOne等注解。在接口上使用@Mapper修饰,在接口方法上使用@SelectOne等注解修饰。就可以直接使用接口.接口方法发起对数据库的请求调用。

手写模拟实现一个简易Mybatis,支持XML和注解方式查询_第12张图片

 手写模拟实现一个简易Mybatis,支持XML和注解方式查询_第13张图片

 手写模拟实现一个简易Mybatis,支持XML和注解方式查询_第14张图片

手写模拟实现一个简易Mybatis,支持XML和注解方式查询_第15张图片

定义好之后,在启动类中进行Mapper扫描即可。

手写模拟实现一个简易Mybatis,支持XML和注解方式查询_第16张图片

手写模拟实现一个简易Mybatis,支持XML和注解方式查询_第17张图片

手写模拟实现一个简易Mybatis,支持XML和注解方式查询_第18张图片

 使用MapperScannerConfigurer进行扫描,给MapperScannerConfigurer传入必要参数

手写模拟实现一个简易Mybatis,支持XML和注解方式查询_第19张图片

 调用MapperScannerConfigurer,执行postProcessBeanDefinitionRegistry

手写模拟实现一个简易Mybatis,支持XML和注解方式查询_第20张图片

使用自定义扫描器扫描指定Mapper接口

手写模拟实现一个简易Mybatis,支持XML和注解方式查询_第21张图片

手写模拟实现一个简易Mybatis,支持XML和注解方式查询_第22张图片

MapperFactoryBean.java是产生代理的核心类,同时在这个类中还会进行接口类与代理类的绑定并传入map中

手写模拟实现一个简易Mybatis,支持XML和注解方式查询_第23张图片

手写模拟实现一个简易Mybatis,支持XML和注解方式查询_第24张图片

手写模拟实现一个简易Mybatis,支持XML和注解方式查询_第25张图片

手写模拟实现一个简易Mybatis,支持XML和注解方式查询_第26张图片

 这样就完成了mapper接口类与代理ProxyFactory的绑定。那么通过getMapper方法获取是怎么产生代理类的呢?

BlogMapper blogMapper = sqlSession.getMapper(BlogMapper.class);

sqlSession类:

手写模拟实现一个简易Mybatis,支持XML和注解方式查询_第27张图片

configuration类:

MapperRegistry类:动态代理对象就是在这里产生的

手写模拟实现一个简易Mybatis,支持XML和注解方式查询_第28张图片

MapperProxyFactory类:执行newInstance创建代理对象并返回给getMapper

手写模拟实现一个简易Mybatis,支持XML和注解方式查询_第29张图片

当getMapper得到的动态代理类执行Blog blog3 = blogMapper.selectBlog(query);就会触发到

 InvocationHandlerProxy代理类的invoke方法,因为这个代理类继承了InvocationHandler接口。

手写模拟实现一个简易Mybatis,支持XML和注解方式查询_第30张图片

在这个InvocationHandlerProxy代理类的invoke方法内,通过传入的sqlSession调用内部的JDBC执行查询并返回结果。

以上就是本手写代码的大致调用过程,本例子有很多细节都没有实现(如入参解析,返回结果解析,update接口功能,动态sql等等),而mybatis使用了Handler等诸多处理类进行优雅处理,mybatis这块的源码也是值得继续深入学习的。

再次附上代码下载地址:手写简易mybatis-Java文档类资源-CSDN下载

 

 

 

 

 

 

 

你可能感兴趣的:(mybatis专栏,xml,spring,java)