MapperScannerConfigurer在mybatis-spring的妙用
来源:互联网 发布:js input value 赋值 编辑:程序博客网 时间:2024/06/06 00:02
概述
在mybatis中我们经常这样定义OrderInfoMapper这样的接口,然后配置OrderInfoMapper.xml映射到OrderInfoMapper,就可以直接注入OrderInfoMapper
public interface OrderInfoMapper { int insert(Order order);}
定义一个SQL操作
<insert id="insert" parameterType="com.test.order.bo.Order">INSERT IGNORE INTO orderdetail...</insert>
就可以直接注入使用
@Autowired private OrderInfoMapper orderInfoMapper; @Override public int insertExample(Order order) { int effectNum = orderInfoMapper.insert(order); return effectNum; }
XML配置扫描包路径,Spring会扫描指定包中的类与相应的mapper文件对应起来
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"> <property name="basePackage" value="com.test.soa.order.mapper"/> <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/> </bean>
那么Spring到底是怎么建立数据库的连接然后执行SQL操作?这其实都要归功于MapperScannerConfigurer的功能。MapperScannerConfigurer实现了BeanDefinitionRegistryPostProcessor。
BeanDefinitionRegistryPostProcessor的使用
BeanDefinitionRegistryPostProcessor接口有获取BeanDefinitionRegistry的能力,BeanDefinitionRegistry是Spring所有Bean的注册中心,通过这个注册中心可以自定义修改已经定义好的Bean,这样可以加工甚至替换已经定义的Bean,高度化定制Bean的创建。
public interface BeanDefinitionRegistryPostProcessor extends BeanFactoryPostProcessor { /** * Modify the application context's internal bean definition registry after its * standard initialization. All regular bean definitions will have been loaded, * but no beans will have been instantiated yet. This allows for adding further * bean definitions before the next post-processing phase kicks in. * @param registry the bean definition registry used by the application context * @throws org.springframework.beans.BeansException in case of errors */ void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException;}
MapperScannerConfigurer实现了postProcessBeanDefinitionRegistry方法,将已经注册好的Bean重新替换
public class MapperScannerConfigurer implements BeanDefinitionRegistryPostProcessor, InitializingBean, ApplicationContextAware, BeanNameAware {public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException { if (this.processPropertyPlaceHolders) { processPropertyPlaceHolders(); } ClassPathMapperScanner scanner = new ClassPathMapperScanner(registry); scanner.setAddToConfig(this.addToConfig); scanner.setAnnotationClass(this.annotationClass); scanner.setMarkerInterface(this.markerInterface); scanner.setSqlSessionFactory(this.sqlSessionFactory); scanner.setSqlSessionTemplate(this.sqlSessionTemplate); scanner.setSqlSessionFactoryBeanName(this.sqlSessionFactoryBeanName); scanner.setSqlSessionTemplateBeanName(this.sqlSessionTemplateBeanName); scanner.setResourceLoader(this.applicationContext); scanner.setBeanNameGenerator(this.nameGenerator); scanner.registerFilters(); scanner.scan(StringUtils.tokenizeToStringArray(this.basePackage, ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS)); }...}
ClassPathMapperScanner的doScan方法,会将mapper包中的类替换成MapperFactoryBean,MapperFactoryBean实现了FactoryBean接口,每次生成对应Bean的时候,其实调用的FactoryBean的getObject方法。也就是说我们在注入OrderInfoMapper的时候,其实调用的是FactoryBean的getObject方法,而这个方法会生成OrderInfoMapper的代理类MapperProxy的实例。mybatis-spring就这样“偷梁换柱”的把mapper包中的类的实例替换成了代理类的实例
@Override public Set<BeanDefinitionHolder> doScan(String... basePackages) { Set<BeanDefinitionHolder> beanDefinitions = super.doScan(basePackages); if (beanDefinitions.isEmpty()) { logger.warn("No MyBatis mapper was found in '" + Arrays.toString(basePackages) + "' package. Please check your configuration."); } else { for (BeanDefinitionHolder holder : beanDefinitions) { GenericBeanDefinition definition = (GenericBeanDefinition) holder.getBeanDefinition(); if (logger.isDebugEnabled()) { logger.debug("Creating MapperFactoryBean with name '" + holder.getBeanName() + "' and '" + definition.getBeanClassName() + "' mapperInterface"); } // the mapper interface is the original class of the bean // but, the actual class of the bean is MapperFactoryBean definition.getPropertyValues().add("mapperInterface", definition.getBeanClassName()); definition.setBeanClass(MapperFactoryBean.class); definition.getPropertyValues().add("addToConfig", this.addToConfig); boolean explicitFactoryUsed = false; if (StringUtils.hasText(this.sqlSessionFactoryBeanName)) { definition.getPropertyValues().add("sqlSessionFactory", new RuntimeBeanReference(this.sqlSessionFactoryBeanName)); explicitFactoryUsed = true; } else if (this.sqlSessionFactory != null) { definition.getPropertyValues().add("sqlSessionFactory", this.sqlSessionFactory); explicitFactoryUsed = true; } if (StringUtils.hasText(this.sqlSessionTemplateBeanName)) { if (explicitFactoryUsed) { logger.warn("Cannot use both: sqlSessionTemplate and sqlSessionFactory together. sqlSessionFactory is ignored."); } definition.getPropertyValues().add("sqlSessionTemplate", new RuntimeBeanReference(this.sqlSessionTemplateBeanName)); explicitFactoryUsed = true; } else if (this.sqlSessionTemplate != null) { if (explicitFactoryUsed) { logger.warn("Cannot use both: sqlSessionTemplate and sqlSessionFactory together. sqlSessionFactory is ignored."); } definition.getPropertyValues().add("sqlSessionTemplate", this.sqlSessionTemplate); explicitFactoryUsed = true; } if (!explicitFactoryUsed) { if (logger.isDebugEnabled()) { logger.debug("Enabling autowire by type for MapperFactoryBean with name '" + holder.getBeanName() + "'."); } definition.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_BY_TYPE); } } } return beanDefinitions; }
最后OrderInfoMapper.insert真正执行的方法是MapperMethod的execute
public class MapperMethod {....public Object execute(SqlSession sqlSession, Object[] args) { Object result; if (SqlCommandType.INSERT == command.getType()) { Object param = method.convertArgsToSqlCommandParam(args); result = rowCountResult(sqlSession.insert(command.getName(), param)); } else if (SqlCommandType.UPDATE == command.getType()) { Object param = method.convertArgsToSqlCommandParam(args); result = rowCountResult(sqlSession.update(command.getName(), param)); } else if (SqlCommandType.DELETE == command.getType()) { Object param = method.convertArgsToSqlCommandParam(args); result = rowCountResult(sqlSession.delete(command.getName(), param)); } else if (SqlCommandType.SELECT == command.getType()) { if (method.returnsVoid() && method.hasResultHandler()) { executeWithResultHandler(sqlSession, args); result = null; } else if (method.returnsMany()) { result = executeForMany(sqlSession, args); } else if (method.returnsMap()) { result = executeForMap(sqlSession, args); } else { Object param = method.convertArgsToSqlCommandParam(args); result = sqlSession.selectOne(command.getName(), param); } } else { throw new BindingException("Unknown execution method for: " + command.getName()); } if (result == null && method.getReturnType().isPrimitive() && !method.returnsVoid()) { throw new BindingException("Mapper method '" + command.getName() + " attempted to return null from a method with a primitive return type (" + method.getReturnType() + ")."); } return result; }
- MapperScannerConfigurer在mybatis-spring的妙用
- MapperScannerConfigurer在mybatis-spring的妙用
- mybatis-spring:MapperScannerConfigurer、MapperScannerConfigurer
- spring-mybatis整合-MapperScannerConfigurer
- 【spring+mybatis】MapperScannerConfigurer
- Spring-MyBatis 之 MapperScannerConfigurer
- spring mybatis 之MapperScannerConfigurer
- 【spring+mybatis】MapperScannerConfigurer
- org.mybatis.spring.mapper.MapperScannerConfigurer
- Spring整合Mybatis(MapperScannerConfigurer方式)
- mybatis-spring 源码分析MapperScannerConfigurer
- MapperScannerConfigurer方法整合spring+mybatis
- spring mvc + mybatis 之MapperScannerConfigurer
- Spring与Mybatis整合的MapperScannerConfigurer处理过程源码分析
- Spring与Mybatis整合的MapperScannerConfigurer处理过程源码分析
- Spring与Mybatis整合的MapperScannerConfigurer处理过程源码分析
- Spring与Mybatis整合的MapperScannerConfigurer处理过程
- Spring与Mybatis整合的MapperScannerConfigurer处理过程源码分析
- iOS中代理属性为什么要用Weak修饰?
- 扫一扫
- Android开发中常犯的错误有哪些
- linux, bsd
- base operand of '->' has non-pointer type 'JNIEnv {aka _JNIEnv}'和Method 'GetStringUTFChars' could no
- MapperScannerConfigurer在mybatis-spring的妙用
- POJ 3080 Blue Jeans【多串最长子串】
- 基于bootstrap table分页数据及行内编辑和导出数据(二)导出数据
- HDU 2870 Largest Submatrix(dp最大子矩阵和)
- Python中re(正则表达式)模块学习
- 使用jquery的ajax需要注意的地方dataType的设置 (目前我也不是很清楚哎)
- Android 中的线程是如何调度
- jQuery隐藏显示
- beego结合bootstrap table和x-editable用于merit价值和成果管理系统