通过MapperScannerConfigurer配置Mybatis的一点研究
来源:互联网 发布:数组发筛选100以内素数 编辑:程序博客网 时间:2024/06/07 17:36
今天通过MapperScannerConfigurer来自动扫描存放Mapper接口的包来自动获得Mapper在Spring中的注册,顺带研究了一下Mybatis是如何实现不在接口上面加注解也能识别的到接口的,同时探究了注册进入Spring的Mapper映射器和***Mapper.xml是如何进行对应的。
首先来一段配置代码,配置好自动扫描路径,sqlSessionFactory和dataSource就可以了。
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"> <property name="basePackage" value="com.recom.dao.in" /></bean><bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <property name="dataSource" ref="dataSource"/> <property name="mapperLocations" value="classpath:/recom-stastic-conf/ArticleInfoDailyStatMapper.xml"/> <property name="configLocation" value="classpath:/sqlmap/MapperConfig.xml"/></bean><bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"> ****省略配置内容************</bean>
这个适合,Mybatis会扫描com.recom.dao.in 下面的所有接口(interface)类型的接口,由于没有指定要扫描的接口类型或者注解类型,默认的情况下MapperScannerConfigurer类中
protected void registerDefaultFilters() { boolean acceptAllInterfaces = true; // if specified, use the given annotation and / or marker interface if (MapperScannerConfigurer.this.annotationClass != null) { addIncludeFilter(new AnnotationTypeFilter(MapperScannerConfigurer.this.annotationClass)); acceptAllInterfaces = false; } // override AssignableTypeFilter to ignore matches on the actual marker interface if (MapperScannerConfigurer.this.markerInterface != null) { addIncludeFilter(new AssignableTypeFilter(MapperScannerConfigurer.this.markerInterface) { @Override protected boolean matchClassName(String className) { return false; } }); acceptAllInterfaces = false; } if (acceptAllInterfaces) { // default include filter that accepts all classes addIncludeFilter(new TypeFilter() { public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException { return true; } }); } }
当没有指定接口和注解类型的时候,默认把所有接口类型加入扫描的includeFilter里面。
最后在 ClassPathScanningCandidateComponentProvider 的
public Set findCandidateComponents(String basePackage) 方法里面
try {MetadataReader metadataReader = his.metadataReaderFactory.getMetadataReader(resource); if (isCandidateComponent(metadataReader)) { ScannedGenericBeanDefinition sbd = new ScannedGenericBeanDefinition(metadataReader); sbd.setResource(resource); sbd.setSource(resource); if (isCandidateComponent(sbd)) { if (debugEnabled) { logger.debug("Identified candidate component class: " + resource); } candidates.add(sbd); }
将BeanDefinition 加入候选列表。这样就完成了对Mapper映射器接口的扫描加载。
当调用Mapper接口的方法时,是IOC通过代理反射完成的,
调用如下接口的方法。
public interface ArticleInfoDailyStatDao { List<ArticleStatsInfo> queryArticleStatsInfo(String after);}
反射会执行invoke方法,实际调用的是final Object result = mapperMethod.execute(args);
public class MapperProxy implements InvocationHandler, Serializable { private static final long serialVersionUID = -6424540398559729838L; private SqlSession sqlSession; private <T> MapperProxy(SqlSession sqlSession) { this.sqlSession = sqlSession; } public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { if (method.getDeclaringClass() == Object.class) { return method.invoke(this, args); } final Class<?> declaringInterface = findDeclaringInterface(proxy, method); final MapperMethod mapperMethod = new MapperMethod(declaringInterface, method, sqlSession); final Object result = mapperMethod.execute(args); if (result == null && method.getReturnType().isPrimitive() && !method.getReturnType().equals(Void.TYPE)) { throw new BindingException("Mapper method '" + method.getName() + "' (" + method.getDeclaringClass() + ") attempted to return null from a method with a primitive return type (" + method.getReturnType() + ")."); } return result; }
跟进去看一下org.apache.ibatis.binding.MapperMethod
初始化的时候会加载很多参数
public MapperMethod(Class<?> declaringInterface, Method method, SqlSession sqlSession) { paramNames = new ArrayList<String>(); paramPositions = new ArrayList<Integer>(); this.sqlSession = sqlSession; this.method = method; this.config = sqlSession.getConfiguration(); this.hasNamedParameters = false; this.declaringInterface = declaringInterface; this.objectFactory = config.getObjectFactory(); setupFields(); setupMethodSignature(); setupCommandType(); validateStatement(); }
其中 setupFields(),解释了Mapper接口的方法被调用之后,执行的指令的内容:
当前接口的完全路径 + 当前执行的方法名。
private void setupFields() { this.commandName = declaringInterface.getName() + "." + method.getName(); }
这也要求配置的****Mapper.xml 里面的namespace一定要写完整写正确才可以匹配的到
<mapper namespace="com.recom.dao.in.ArticleInfoDailyStatDao">*****省略其他内容 <resultMap id="ArticleInfoDailyResultMap" type="com.recom.domain.ArticleStatsInfo"> **************** </resultMap> ****************<select id="queryArticleStatsInfo" resultMap="ArticleInfoDailyResultMap">
- 通过MapperScannerConfigurer配置Mybatis的一点研究
- MyBatis MapperScannerConfigurer配置
- MyBatis MapperScannerConfigurer配置
- MyBatis MapperScannerConfigurer配置
- Mybatis MapperScannerConfigurer 配置
- 使用MapperScannerConfigurer简化MyBatis配置
- Mybatis MapperScannerConfigurer配置问题总结
- 关于Spring整合mybatis时配置MapperScannerConfigurer的问题
- mybatis-spring:MapperScannerConfigurer、MapperScannerConfigurer
- mybatis整合spring使用MapperScannerConfigurer配置问题
- mybatis-spring集成:配置多数据库源中遇到的问题--MapperScannerConfigurer配置
- Mybatis与Spring集成源码研究之MapperScannerConfigurer
- MapperScannerConfigurer在mybatis-spring的妙用
- MapperScannerConfigurer在mybatis-spring的妙用
- MyBatis MapperScannerConfigurer配置——MyBatis学习笔记之八
- MyBatis MapperScannerConfigurer配置——MyBatis学习笔记之一
- 配置MapperScannerConfigurer
- spring 整合mybatis配置 MapperScannerConfigurer,无法读配置文件错误
- JMeter学习-022-JMeter 分布式测试(性能测试大并发、远程启动解决方案)
- ThinkPHP整合微信支付之Native 扫码支付 模式一
- C++中static数据成员详解
- struts action chain和hibernate 事务拦截器的一个诡异问题
- 处理点击select之外的元素来触发select下拉
- 通过MapperScannerConfigurer配置Mybatis的一点研究
- Red Hat linux 6.5 学习使用笔记《四》bash特性详解
- c#参数数组
- 关于MYSQL优化的一些个人见解
- POJ 2104 K-th Number 归并树
- MYSQL 常用语句
- 联合主键和复合主键区别
- JavaScript中对非Boolean型变量进行if判断
- 第十五周项目3-B-树的基本操作