首先看下我们spring和mybatis扫描包的时候是怎样写:
有两种写法:
第一种写法:
<mybatis-spring:scan base-package="com.gupaoedu.crud.dao"/>
第二种写法:
<bean id="mapperScanner" class="org.mybatis.spring.mapper.MapperScannerConfigurer"> <property name="basePackage" value="com.gupaoedu.crud.dao"/> </bean>
第一种写法是spring解析xml文件时提供了一个钩子方法给其他框架去解析他们自定义的标签
1.那为什么要去解析mybatis的NameSpaceHander呢他又没注入到容器里?
2.图中时scan而不是mybatis-spring:scan
问题解析:
首先配置applcationcContext.xml时
会加入这个文件,如果不加入的话就会xml的约束会提示mybatis-spring:scan报错的
spring启动的时候会查找META-INF/spring.handlers 这个文件下的内容,下图所示
这里就关联上了,spring会扫描这个文件下的内容
因此这下面三个东西就关联上了。<mybatis-spring:scan > 标签找到 http://mybatis.org/schema/mybatis-spring 再找到org.mybatis.spring.config.NamespaceHandler
这样就可以解析自定义标签了
http://mybatis.org/schema/mybatis-spring org.mybatis.spring.config.NamespaceHandler mybatis-spring
下面这一点就是注入相应的解析器代码
现在分析spring+mybatis结合的入口分析
写法一入口查看:
写一部查看一下解析器里面的内容
写法二也是通过ClassPathMapperScanner扫描包的,所以这里也一同分析方法二
因为扫描的操作是一样的,后面再分析是怎么扫描的:
写法二是注入MapperScannerConfigurer: 打开查看
因为实现了BeanDefinitionRegistryPostProcessor 所以注入BeanDefinition后会调用postProcessBeanDefinitionRegistry
从上图所示也是和写法一一样通过ClassPathMapperScanner 来扫描包
查看ClassPathMapperScanner的继承的类
我们查看一下ClassPathMapperScanner.scan方法 他是他父类的方法来的
然后再查看doScan 这个ClassPathMapperScanner 重写了父类的方法:
现在查看一下this.processBeanDefinitions(beanDefinitions);
帮接口都注入了实现类mapperFactoryBean,
mapperFactoryBean如下
mapperFactoryBean构造方法是要带上类名的。。因为实现了FactoryBean 从容器取出对象时会调用getObject。从getOject里可以看到
this.getSqlSession().getMapper(this.mapperInterface);
这就是mybatis操作数据库的操作了。。所以文章也到此结束了