首页 > 编程知识 正文

mybatis注解的使用,@mapper注解的使用

时间:2023-05-04 20:45:02 阅读:28420 作者:2164

一.使用映射扫描

MapperScan注释详细说明了如何使用MapperScan注释; MapperScan大大简化了mybatis的使用成本,不需要为每个Java接口放置@Mapper接口,也不需要sqlsessiontemplate.get mapper [ person Dao.cllate ]

@Autowired从spring容器中检索对象,并知道检索到的对象始终是代理对象。 为什么这么说,是因为我们给了接口地址。 如果我的mybatis-spring在spring中注册代理对象呢?

首先,@MapperScan注释是如何分析的?

看看import的MapperScannerRegistrar.class。 由于实现了ImportBeanDefinitionRegistrar接口,因此在spring启动时将调用此方法。

@ overridepublicvoidregisterbeandefinitions (注释元数据端口分类元数据, beandefinitionregistryregistry (annotationattributesmapperscanattrs=annotation attributes.from map (导入分类元数据映射扫描器!=null (注册beandefinitions (映射扫描,注册); }//mappers读取can注释设置的路线图,然后使用ClassPathMapperScanner访问语音识别器(annotationattributesannoattrs ), beandefinitionregistryregistry (classpathmapperscannerscanner=newclasspathmapperscanner (registry ) ); //thischeckisneededinspring 3.1 optional.of nullable (resource loader ).if present (scanner 33603360 setresourceloader ); Class? extendsannotationannotationclass=anno attrs.getclass (annotation class ); if (! annotation.class.equals (annotationclass ) (scanner.setannotationclass ) annotation class ); }班? marker接口=anno attrs.getclass (marker接口); if (! class.class.equals (标记接口) ) scanner.setmarkerinterface (标记接口); }班? extendsbeannamegeneratorgeneratorclass=anno attrs.getclass (name generator ); if (! beanname generator.class.equals (generator class ) ) scanner.setbeannamegenerator (beanutils.instantiate class ) ) genener }班? extendsmapperfactorybeanmapperfactorybeanclass=anno attrs.getclass (factory bean ); if (! mapperfactorybean.class.equals (mapperfactorybeanclass ) ) scanner.setmapperfactorybean (beanutils.instatiateclaseclases ) } scanner.setsqlsessiontemplatebeanname (anno attrs.getstring (sqlsessiontemplateref ) ); scanner.setsqlsessionfactorybeanname (anno attrs.getstring (sqlsessionfactoryref ) ); liststringbasepackages=new ArrayList (; 基本包。

addAll( Arrays.stream(annoAttrs.getStringArray("value")) .filter(StringUtils::hasText) .collect(Collectors.toList())); basePackages.addAll( Arrays.stream(annoAttrs.getStringArray("basePackages")) .filter(StringUtils::hasText) .collect(Collectors.toList())); basePackages.addAll( Arrays.stream(annoAttrs.getClassArray("basePackageClasses")) .map(ClassUtils::getPackageName) .collect(Collectors.toList())); scanner.registerFilters(); scanner.doScan(StringUtils.toStringArray(basePackages)); }

ClassPathMapperScanner.java的doScan(StringUtils.toStringArray(basePackages));

@Override public Set<BeanDefinitionHolder> doScan(String... basePackages) { //获取到Java类的beanDefines 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 { processBeanDefinitions(beanDefinitions); } return beanDefinitions; }

Set beanDefinitions = super.doScan(basePackages);会获取到Java类的beanDefine,但是我们这里的Java类是我们声明的接口,并不是可以实例化的类,所以spring是无法实例化成bean的,那么需要怎么做呢?接着往下看 processBeanDefinitions(beanDefinitions);

private void processBeanDefinitions(Set<BeanDefinitionHolder> beanDefinitions) { GenericBeanDefinition definition; for (BeanDefinitionHolder holder : beanDefinitions) { definition = (GenericBeanDefinition) holder.getBeanDefinition(); String beanClassName = definition.getBeanClassName(); LOGGER.debug(() -> "Creating MapperFactoryBean with name '" + holder.getBeanName() + "' and '" + beanClassName + "' mapperInterface"); // the mapper interface is the original class of the bean // but, the actual class of the bean is MapperFactoryBean definition.getConstructorArgumentValues().addGenericArgumentValue(beanClassName); // issue #59 //这里是重点,把beanDefine的Class换了mapperFactoryBean definition.setBeanClass(this.mapperFactoryBean.getClass());(1) 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; } 。。。省略部分代码 }

我们看到在(1)这里把BeanClass替换成了mapperFactoryBean,而这个类是啥样的呢?


这个类在scanner创建的时候被创建;


(1)注释里介绍了单独使用这个类的用法,也就是手动获取一个接口的代理对象Mapper的方法;
(2)看这个类的原理,这个类继承了FactoryBean,所以spring实例话它的时候肯定会调用getObject()方法,

@Override public T getObject() throws Exception { return getSqlSession().getMapper(this.mapperInterface); }

到这里之后,如果看过我的上一篇博客mybatis初始化的就一切都清晰了,后面的获取代理对象是mybatis内部实现的;会去获取mybatis的Configuration里代理对象;

二、MapperScannerConfigurer的原理和@MapperScan原理是一样的:


MapperScannerConfigurer实现了BeanDefinitionRegistryPostProcessor,所以spring会调用到

@Override public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) { 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。

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。