广告
返回顶部
首页 > 资讯 > 后端开发 > Python >Spring整合Mybatis实操分享
  • 756
分享到

Spring整合Mybatis实操分享

2024-04-02 19:04:59 756人浏览 独家记忆

Python 官方文档:入门教程 => 点击学习

摘要

目录mybatis的基本工作原理分析需要解决的问题spring中Bean的产生过程解决问题总结在介绍Spring整合Mybatis原理之前,我们得先来稍微介绍Mybatis的工作原理

在介绍Spring整合Mybatis原理之前,我们得先来稍微介绍Mybatis的工作原理。

Mybatis的基本工作原理

Mybatis中,我们可以使用一个接口去定义要执行sql,简化代码如下: 定义一个接口,@Select表示要执行查询sql语句。

 public interface UserMapper { 
 @Select("select * from user where id = #{id}") 
 User selectById(Integer id);
 }

执行代码:

 InputStream inputStream = Resources.getResourceAsStream("mybatis.xml" ); 
 SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder(). build(inputStream);
 SqlSession sqlSession = sqlSessionFactory.openSession(); 
 // 以下使我们需要关注的重点 
 UserMapper mapper = sqlSession.getMapper(UserMapper.class); 
 Integer id = 1; 
 User user = mapper.selectById(id);

Mybatis的目的是:使得程序员能够以调用方法的方式执行某个指定的sql,将执行sql的底层逻辑进行了封装。 这里重点思考以下mapper这个对象,当调用SqlSession的getMapper方法时,会对传入的接口生成一个 代理对象,而程序要真正用到的就是这个代理对象,在调用代理对象的方法时,Mybatis会取出该方法所对应的sql语句,然后利用JDBC去执行sql语句,最终得到结果。

分析需要解决的问题

Spring和Mybatis时,我们重点要关注的就是这个代理对象。因为整合的目的就是:把某个Mapper的代理 对象作为一个bean放入Spring容器中,使得能够像使用一个普通bean一样去使用这个代理对象,比如能 被@Autowire自动注入。 比如当Spring和Mybatis整合之后,我们就可以使用如下的代码来使用Mybatis中的代理对象了:

 @Component 
 public class UserService { 
 @Autowired 
 private UserMapper userMapper; 

 public User getUserById(Integer id) { 
 return userMapper.selectById(id); 
 } 
 }

UserService中的userMapper属性就会被自动注入为Mybatis中的代理对象。如果你基于一个已经完成整合的项目去调试即可发现,userMapper的类型为: org.apache.ibatis.binding.MapperProxy@41a0aa7d。证明确实是Mybatis中的代理对象。 好,那么现在我们要解决的问题的就是:如何能够把Mybatis的代理对象作为一个bean放入Spring容器中?要解决这个,我们需要对Spring的bean生成过程有一个了解。

Spring中Bean的产生过程

Spring启动过程中,大致会经过如下步骤去生成bean

  • 扫描指定的包路径下的class文件
  • 根据class信息生成对应的BeanDefinition
  • 在此处,程序员可以利用某些机制去修改BeanDefinition
  • 根据BeanDefinition生成bean实例
  • 把生成的bean实例放入Spring容器中

假设有一个A类,假设有如下代码: 一个A类

@Component
 public class A { 
 }

一个B类,不存在@Component注解

 public class B { 
 }

执行如下代码:

AnnotationConfigApplicationContext context = new AnnotationConfigAppl icationContext(AppConfig.class); 
 System.out.println(context.getBean("a"));

输出结果为:com.luban.util.A@6acdbdf5 A类对应的bean对象类型仍然为A类。但是这个结论是不确定的,我们可以利用BeanFactory后置处理器来 修改BeanDefinition,我们添加一个BeanFactory后置处理器:

 @Component 
 public class LubanBeanFactoryPostProcessor implements BeanFactoryPost Processor { 
 @Override 
public void postProcessBeanFactory(ConfigurableListableBeanFactor y beanFactory)
 throws BeansException { 
 BeanDefinition beanDefinition = beanFactory.getBeanDefinition 
("a"); 
beanDefinition.setBeanClassName(B.class.getName()); 
} 
 }

这样就会导致,原本的A类对应的BeanDefiniton被修改了,被修改成了B类,那么后续正常生成的bean对 象的类型就是B类。此时,调用如下代码会报错:

 context.getBean(A.class);

但是调用如下代码不会报错,尽管B类上没有@Component注解:

 context.getBean(B.class);

并且,下面代码返回的结果是:

com.luban.util.B@4b1c1ea0

 AnnotationConfigApplicationContext context = new AnnotationConfigAppl icationContext(AppConfig.class); 
 System.out.println(context.getBean("a"));

之所以讲这个问题,是想说明⼀个问题:在Spring中,bean对象跟class没有直接关系,跟 BeanDefinition才有直接关系。 那么回到我们要解决的问题:如何能够把Mybatis的代理对象作为一个bean放入Spring容器中? 在Spring中,如果你想生成一个bean,那么得先生成一个BeanDefinition,就像你想new一个对象实 例,得先有一个class。

解决问题

继续回到我们的问题,我们现在想自己生成一个bean,那么得先生成一个BeanDefinition,只要有了 BeanDefinition,通过在BeanDefinition中设置bean对象的类型,然后把BeanDefinition添加给 Spring,Spring就会根据BeanDefinition⾃动帮我们⽣成⼀个类型对应的bean对象。

所以,现在我们要解决两个问题:

  • Mybatis的代理对象的类型是什么?因为我们要设置给BeanDefinition
  • 我们怎么把BeanDefinition添加给Spring容器?

注意:上文中我们使用的BeanFactory后置处理器,他只能修改BeanDefinition,并不能新增一个 BeanDefinition。我们应该使用Import技术来添加一个BeanDefinition。后面再详细介绍如果使用Import 技术来添加一个BeanDefinition,可以先看一下伪代码实现思路。

假设:我们有一个UserMapper接口,他的代理对象的类型为UserMapperProxy。 那么我们的思路就是这样的,

伪代码如下:

 BeanDefinitoin bd = new BeanDefinitoin();
 bd.setBeanClassName(UserMapperProxy.class.getName()); 
 SprinGContainer.addBd(bd);

但是,这里有一个严重的问题,就是上文中的UserMapperProxy是我们假设的,他表示一个代理类的类 型,然而Mybatis中的代理对象是利用的jdk的动态代理技术实现的,也就是代理对象的代理类是动态生成的,我们根本方法确定代理对象的代理类到底是什么。 所以回到我们的问题:Mybatis的代理对象的类型是什么? 本来可以有两个答案: 1. 代理对象对应的代理类 2. 代理对象对应的接口 那么答案1就相当于没有了,因为是代理类是动态生成的,那么我们来看答案2:代理对象对应的接口如果我们采用答案2,那么我们的思路就是:

BeanDefinition bd = new BeanDefinitoin(); 
 // 注意这⾥,设置的是UserMapper 
 bd.setBeanClassName(UserMapper.class.getName()); 
 SpringContainer.addBd(bd);

但是,实际上给BeanDefinition对应的类型设置为一个接口是行不通的,因为Spring没有办法根据这个 BeanDefinition去new出对应类型的实例,接口是没法直接new出实例的。 那么现在问题来了,我要解决的问题:Mybatis的代理对象的类型是什么? 两个答案都被我们否定了,所以这个问题是无解的,所以我们不能再沿着这个思路去思考了,只能回到最 开始的问题:如何能够把Mybatis的代理对象作为一个bean放入Spring容器中?

总结上文的推理:我们想通过设置BeanDefinition的class类型,然后由Spring自动的帮助我们去生成对应的bean,但是这条路是行不通的。 终极解决方案 那么我们还有没有其他办法,可以去生成bean呢?并且生成bean的逻辑不能由Spring来帮我们做了,得 由我们自己来做。 FactoryBean 有,那就是Spring中的FactoryBean。我们可以利用FactoryBean去自定义我们要生成的bean对象,比如

 @Component
 public class LubanFactoryBean implements FactoryBean { 
 @Override 
public Object getObject() throws Exception { 
 Object proxyInstance = Proxy.newProxyInstance(LubanFactoryBe an.class.
getClassLoader(), new Class[]{UserMapper.class}, new Invoca tionHandler() { 
 @Override 
 public Object invoke(Object proxy, Method method, Object [] args) throws Throwable { 
 if (Object.class.equals(method.getDeclaringClass())) { 
 return method.invoke(this, args); 
 } else { 
 // 执⾏代理逻辑 
 return null; 
 } 
 } 
 }); 
 return proxyInstance; 
 } 
 @Override 
 public Class<?> getObjectType() { 
return UserMapper.class;
 } 
 }

我们定义了一个LubanFactoryBean,它实现了FactoryBean,getObject方法就是用来自定义生成bean 对象逻辑的。 执行如下代码:

 public class Test { 
 public static void main(String[] args) { 
 AnnotationConfigApplicationContext 
context = new AnnotationCo nfigApplicationContext(AppConfig.class); 
 System.out.println("lubanFactoryBean: " + context.getBean
("lu banFactoryBean")); 
 System.out.println("&lubanFactoryBean: " + context.getBean
("& lubanFactoryBean")); 
 System.out.println("lubanFactoryBean-class: " + 
context.getBe an("lubanFactoryBean").getClass()); 
 } 
}

将打印: lubanFactoryBean: com.luban.util.LubanFactoryBean1@4d41cee &lubanFactoryBean: com.luban.util.LubanFactoryBean@3712b94 lubanFactoryBean-class: class com.sun.proxy.Proxy20 从结果我们可以看到,从Spring容器中拿名字为"lubanFactoryBean"的bean对象,就是我们所自定义的 jdk动态代理所生成的代理对象。

所以,我们可以通过FactoryBean来向Spring容器中添加一个自定义的bean对象。上文中所定义的 LubanFactoryBean对应的就是UserMapper,表示我们定义了一个LubanFactoryBean,相当于把 UserMapper对应的代理对象作为一个bean放入到了容器中。 但是作为程序员,我们不可能每定义了一个Mapper,还得去定义一个LubanFactoryBean,这是很麻烦的 事情,我们改造一下LubanFactoryBean,让他变得更通用,

比如:

 @Component 
public class LubanFactoryBean implements FactoryBean { 
// 注意这里 
 private Class mapperInterface;
 public LubanFactoryBean(Class mapperInterface) { 
 this.mapperInterface = mapperInterface; 
 } 
 @Override 
 public Object getObject() throws Exception { 
 Object proxyInstance = Proxy.newProxyInstance(LubanFactoryBe an.class.getClassLoader(), 
new Class[]{mapperInterface}, new Invocat ionHandler() { 
 @Override 
 public Object invoke(Object proxy, Method method, Object [] args) throws Throwable { 
if (Object.class.equals(method.getDeclaringClass())) { 
return method.invoke(this, args); 
 } else { 
 // 执行代理逻辑 
 return null; 
 } 
 } 
 }); 

return proxyInstance; 
 } 
 @Override 
 public Class<?> getObjectType() { 
 return mapperInterface; 
 }
}

改造LubanFactoryBean之后,LubanFactoryBean变得灵活了,可以在构造LubanFactoryBean时,通 过构造传入不同的Mapper接口。 实际上LubanFactoryBean也是一个Bean,我们也可以通过生成一个BeanDefinition来生成一个 LubanFactoryBean,并给构造方法的参数设置不同的值,比如伪代码如下:

BeanDefinition bd = new BeanDefinitoin();
 // 注意一:设置的是LubanFactoryBean 
 bd.setBeanClassName(LubanFactoryBean.class.getName()); 
 // 注意二:表示当前BeanDefinition在生成bean对象时,会通过调用LubanFactoryBean
 的构造方法来生成,并传入UserMapper 
bd.getConstructorArgumentValues().addGenericArgumentValue(UserMapper. class.getName()) 
 SpringContainer.addBd(bd)

特别说一下注意二,表示表示当前BeanDefinition在生成bean对象时,会通过调用LubanFactoryBean的 构造方法来生成,并传入UserMapper的Class对象。那么在生成LubanFactoryBean时就会生成一个 UserMapper接口对应的代理对象作为bean了。 到此为止,其实就完成了我们要解决的问题:把Mybatis中的代理对象作为一个bean放入Spring容器中。

只是我们这是用简单的JDK代理对象模拟的Mybatis中的代理对象,如果有时间,我们完全可以调⽤ Mybatis中提供的方法区生成一个代理对象。这里就不花时间去介绍了。 Import 到这里,我们还有一个事情没有做,就是怎么真正的定义一个BeanDefinition,并把它添加到Spring中, 上文说到我们要利用Import技术,比如可以这么实现:

定义如下类:

public class LubanImportBeanDefinitionReGIStrar implements ImportBea nDefinitionRegistrar { 
 @Override 
 public void registerBeanDefinitions(AnnotationMetadata importing
 ClaSSMetadata, BeanDefinitionRegistry registry) { 
 BeanDefinitionBuilder builder = BeanDefinitionBuilder.generi cBeanDefinition(); 
 AbstractBeanDefinition beanDefinition = builder.getBeanDefin ition(); 
 beanDefinition.setBeanClass(LubanFactoryBean.class); 
 beanDefinition.getConstructorArgumentValues().addGenericArgu mentValue(UserMapper.class);
 // 添加beanDefinition 
 registry.registerBeanDefinition("luban"+UserMapper.class.get SimpleName(),
 beanDefinition); 
 } 
 }

并且在AppConfig上添加@Import注解:

 @Import(LubanImportBeanDefinitionRegistrar.class) 
 public class AppConfig {

这样在启动Spring时就会新增一个BeanDefinition,该BeanDefinition会生成一个LubanFactoryBean对 象,并且在生成LubanFactoryBean对象时会传入UserMapper.class对象,通过LubanFactoryBean内部 的逻辑,相当于会自动生产一个UserMapper接口的代理对象作为一个bean。

总结

总结一下,通过我们的分析,我们要整合Spring和Mybatis,需要我们做的事情如下:

  • 定义一个LubanFactoryBean
  • 定义一个LubanImportBeanDefinitionRegistrar
  • 在AppConfig上添加一个注解@Import(LubanImportBeanDefinitionRegistrar.class)

到此这篇关于Spring整合Mybatis实操分享的文章就介绍到这了,更多相关Spring整合Mybatis内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

--结束END--

本文标题: Spring整合Mybatis实操分享

本文链接: https://www.lsjlt.com/news/147616.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • Spring整合Mybatis实操分享
    目录Mybatis的基本工作原理分析需要解决的问题Spring中Bean的产生过程解决问题总结在介绍Spring整合Mybatis原理之前,我们得先来稍微介绍Mybatis的工作原理...
    99+
    2022-11-13
  • Spring Boot 整合 Thymeleaf 实例分享
    目录一、什么是 Thymeleaf二、整合过程准备过程添加 Thymeleaf 依赖编写实体类和 Controller创建Thymeleaf 模板三、测试一、什么是 Thymelea...
    99+
    2022-11-13
  • Spring Boot 整合 FreeMarker 实例分享
    目录一、前言二、FreeMarker 简介三、准备工作环境准备添加 FreeMarker 依赖添加 FreeMarker 相关配置四、编写实体类和 Controller编写实体类编写...
    99+
    2022-11-13
  • 好程序员Java学习路线分享MyBatis之Spring整合
      好程序员Java学习路线分享MyBatis之Spring整合,Spring、SpringMVC和MyBatis是目前企业开发的三大框架。本章我们将学习将Spring和MyBatis整合到一起,成为我们项目开发的技术骨架。引入依赖首先我们...
    99+
    2023-06-02
  • Spring整合MyBatis的实现步骤
    目录一、Spring 项目整体目录结构二、Spring 整合 MyBatis 开发环境三、Mapper 接口无实现类开发整合MyBatis 是一款常用的持久层框架,使得程序能够以调用...
    99+
    2023-02-24
    Spring 整合 MyBatis Spring与MyBatis整合
  • Spring整合Mybatis思路的示例分析
    这篇文章主要介绍Spring整合Mybatis思路的示例分析,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!引入相关依赖SpringMyabtismysqlMybatsi-spring如何整合?Spring:项目管理框...
    99+
    2023-06-29
  • Spring整合mybatis、springMVC总结
    目录1.mybatis配置流程2.spring配置流程3.spring 整合Dao层4.spring整合Service层5.spring整合MVC层6. spring整合dao-se...
    99+
    2023-05-18
    Spring整合mybatis springMVC Spring整合mybatis Spring整合springMVC
  • 【Spring Boot整合MyBatis教程】
    Spring Boot是由Pivotal团队提供的全新框架,其设计目的是用来简化新Spring应用的初始搭建以及开发过程。该框架使用了特定的方式来进行配置,从而使开发人员不再需要定义样板化的配置。通过这种方式,Spring Boot致力...
    99+
    2023-08-18
    mybatis spring boot java
  • 使用spring如何实现整合mybatis
    今天就跟大家聊聊有关使用spring如何实现整合mybatis,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。1、采用MapperScannerConfigurer,它将会查找类路径下...
    99+
    2023-05-31
    spring mybatis 整合
  • Spring+SpringMVC+MyBatis整合实战(SSM框架)
    目录SpringMVCSpringMyBatis项目结构maven配置文件pom.xmlwebapp配置文件web.xmlspring配置文件applicationContext.x...
    99+
    2022-11-12
  • Spring Boot整合mybatis(一)实例代码
    sprig-boot是一个微服务架构,加快了spring工程快速开发,以及简便了配置。接下来开始spring-boot与mybatis的整合。创建一个maven工程命名为spring-boot-entity,pom.xml文件配置如下:&l...
    99+
    2023-05-31
    spring boot 整合
  • Spring + Spring Boot + MyBatis + MongoDB的整合教程
    前言我之前是学Spring MVC的,后面听同学说Spring Boot挺好用,极力推荐我学这个鬼。一开始,在网上找Spring Boot的学习资料,他们博文写得不是说不好,而是不太详细。我就在想我要自己写一篇尽可能详细的文章出来,下面话不...
    99+
    2023-05-30
    springboot mybatis mongodb
  • SSM框架整合(Spring+SpringMVC+MyBatis)
    【SSM的系统架构】【整合概述】  MyBatis和Spring整合,通过Spring管理mapper接口。  使用mapper的扫描器自动扫描mapper接口在Spring中进行注册。  通过Spring管理Service接口。  使用配...
    99+
    2023-06-03
  • Spring+SpringMVC+MyBatis+Maven框架整合
    本文记录了Spring+SpringMVC+MyBatis+Maven框架整合的记录,主要记录以下几点 一、Maven需要引入的jar包 二、Spring与SpringMVC的配置分离&...
    99+
    2022-10-18
  • SSM(Spring+SpringMVC+Mybatis)框架整合
    1、数据准备 SET FOREIGN_KEY_CHECKS=0; -- ---------------------------- -- Table structure for `admin` -- ------------------...
    99+
    2014-11-03
    SSM(Spring+SpringMVC+Mybatis)框架整合
  • Spring整合Mybatis详细步骤
    目录一、基本介绍1.1 mybatis使用步骤:1.2 Spring整合mybatis步骤:二、mybatis核心配置三、Spring核心配置四、数据库与对应的POJO实体类五、da...
    99+
    2022-11-12
  • 详解Spring如何整合Mybatis
    第一步 导入相关jar包 <dependencies> <!--连接mysql--> <!-- https://mvnreposit...
    99+
    2022-11-12
  • Spring整合Mybatis的全过程
    1.Spring配置文件 1.1配置数据库连接池 <!--读取文件--> <util:properties id="config" location="cl...
    99+
    2022-11-12
  • Spring整合Mybatis具体代码实现流程
    目录原始方式读取mybatis配置文件,获取SqlSession SqlSessionFactory 等 package com.atguigu.rj1192.zyk; import...
    99+
    2022-11-13
  • Spring整合MyBatis的实现方法是什么
    这篇文章主要讲解了“Spring整合MyBatis的实现方法是什么”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Spring整合MyBatis的实现方法是什么”吧!一、Spring 项目整体...
    99+
    2023-07-05
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作