Spring整合Mybatis一文讲透,手把手带你实操

说实话,在讲Mybatis原理之前,首先应该了解一下Mybatis本身是怎么玩的。
例如,有一个 UserMapper 接口,其中写入了 @Select(“从用户中选择”)之类的内容。
看似简单,背后却蕴藏着很多学问。
Mybatis的最终目标是让你通过调用方法来执行SQL,隐藏所有繁琐的JDBC操作。

有趣的是,当你通过SqlSession.getMapper(UserMapper.class)获取userMapper对象时,Mybatis会偷偷地给你一个org.apache.ibatis.binding.MapperProxy类型的代理对象。
您实际上对该代理的称呼,例如 userMapper.findUsers()。
Mybatis会从方法名中解析出对应的sql,然后使用JDBC从数据库中检索数据。
这个代理对象从哪里来?它是依靠JDK动态代理技术来实现的。

但问题是,如何将这个代理对象注入到Spring容器中呢?这里我们首先要了解Spring是如何创建对象的。
比如有一个类A,如果直接re A(),结果仍然是A类型的对象,这是什么意思呢?表明Spring创建的对象与该类没有直接的联系。
关键是看BeanDefinition。
您可以使用 BeanFactoryPostProcessor 更改 A 类的定义,并让 Spring 创建 B 类的对象。
这就是它的工作原理。

但是直接改变BeanDefinition是不行的,因为接口不能直接new。
这就迫使我们改变思路:既然Spring依赖BeanDefinition来创建对象,那我不妨自己创建一个BeanDefinition。
但这里有一个问题。
接口和动态代理类都不起作用。
我应该怎么办?
这时候就应该使用FactoryBean了。
例如,定义一个LubanFactoryBean,实现FactoryBean接口,在getObject中编写逻辑生成代理对象。
运行时,你会发现从容器中获取的userMapper就是Mybatis创建的代理对象。
更棒的是,你可以让LubanFactoryBean变得更加通用,在构建时传递不同的Mapper接口,这样你就不需要为每个Mapper编写重复的代码。

至于如何将这个FactoryBean添加到Spring中,使用Import技术。
例如,定义一个ImportBeanDefinitionRegistrar并在AppConfig中使用@Import进行注释。
Spring会在你启动时自动为你注册UserMapper代理对象。

简单来说,整个过程就是:首先定义一个通用的FactoryBean,并让它在getObject中生成一个代理对象;然后使用Import技术将这个FactoryBean导入到Spring容器中;最后,Spring 会将代理对象作为常规 bean 进行管理。
这样Mybatis的Mapper就可以和Spring的IoC无缝连接了。

我亲自测试过,使用FactoryBean确实可以完美解决代理对象注入问题。
虽然过程有点复杂,但是原理其实还是很清楚的。
我记得的数据是动态代理对象的生成时间在纳秒左右,但是具体数字可能要查看官方文档。

在sql中, statement, PreparedStatement有什么用?