1.三万字带你彻底吃透MyBatis源码!源码!源码
2.java通过反射拿到mybatis中的源码sql语句并操作怎么用什么时候用?
3.å¦ä½å®ç°mybatisçsqlsessiontemplate
4.mybatis springä»ç»ã使ç¨ãå®ç°åç
三万字带你彻底吃透MyBatis源码!!源码
随着互联网的源码迅猛发展,MyBatis逐渐成为了Java开发者不可或缺的源码liquidbounce源码框架技术。许多大厂在面试中偏好问及MyBatis的源码底层原理及源码实现,这表明了其在技术栈中的源码重要性。本文旨在全面解析MyBatis源码,源码帮助开发者深入理解这一强大的源码框架。为了方便学习,源码推荐大家先收藏后仔细研读。源码
MyBatis源码在封装了JDBC之后,源码实现了对数据库操作的源码高级抽象。无论是源码获取连接、预编译语句、参数封装还是执行SQL,其核心步骤并未改变。
解析过程始于通过`ClassLoader.getResourceAsStream`方法获取配置文件路径。大秀源码2020这个过程确保了MyBatis能正确加载配置信息,进而解析XML文件,构建配置中心。
解析XML文件的关键在于`parseConfiguration`和`mapperParser.parse`方法。前者用于解析配置文件中的`Environment`、`Setting`等信息,后者则专注于解析Mapper映射器,将其与工厂类进行绑定。
构建`SqlSessionFactory`的在线改图网站源码过程涉及解析Mapper映射器,生成`MappedStatement`对象,以及将接口类型与工厂类绑定。最终,`DefaultSqlSessionFactory`被创建,用于管理会话生命周期。
会话的创建通过`openSession`方法完成,该方法实例化了`Executor`来执行SQL。`Executor`的配置则决定了事务管理和执行器类型。同时,搭建php环境 源码`Transaction`的管理分为两种方式,以确保数据的一致性和完整性。
获取Mapper对象时,通过`mapperRegistry.getMapper`方法,该方法从`MapperRegistry`的`knownMappers`中获取接口类型和对应的工厂类。代理对象`MapperProxy`由JDK动态代理生成,用于执行实际的数据库操作。
执行SQL时,调用代理对象的翻牌记忆游戏源码`invoke`方法,进而调用`execute`方法。无论是查询还是其他操作,均遵循此流程。在查询场景下,`selectOne`与`selectList`功能实现相同,仅在参数处理上有所差异。
`MappedStatement`对象负责存储SQL信息,包括执行策略、参数类型等。`CacheKey`的生成则基于`BoundSql`内容,用于缓存结果,提高效率。
通过以上解析,我们可以看到MyBatis源码的简洁与高效。深入理解其结构与机制,不仅有助于提高开发效率,还能增强对数据库操作的理解。总的来说,MyBatis的源码并不复杂,只需耐心研读,两三天内即可掌握其核心。
java通过反射拿到mybatis中的sql语句并操作怎么用什么时候用?
操作。具体的步骤如下:获取 MyBatis 中的 MappedStatement 对象。可以通过 SqlSession 的 getConfiguration() 方法获取 Configuration 对象,然后再通过 Configuration 对象的 getMappedStatement() 方法获取 MappedStatement 对象。
从 MappedStatement 对象中获取 BoundSql 对象,即 SQL 语句绑定的参数对象。
从 BoundSql 对象中获取 SQL 语句字符串。可以通过调用 getSql() 方法获取 SQL 语句字符串。
对 SQL 语句进行相应的操作。例如,可以对 SQL 语句进行修改、输出等操作。
Java 通过反射获取 MyBatis 中的 SQL 语句的代码示例:
SqlSession sqlSession = sqlSessionFactory.openSession();
try {
// 获取 MappedStatement 对象
MappedStatement mappedStatement = sqlSession.getConfiguration().getMappedStatement("com.example.mapper.selectUser");
// 获取 BoundSql 对象
BoundSql boundSql = mappedStatement.getBoundSql(paramObject);
// 获取 SQL 语句字符串
String sql = boundSql.getSql();
// 对 SQL 语句进行相应的操作
// ...
} finally {
sqlSession.close();
}
需要注意的是,在使用反射获取 SQL 语句时,要注意保护用户隐私和安全,以免发生 SQL 注入等问题。
å¦ä½å®ç°mybatisçsqlsessiontemplate
SqlSession sqlSession = null;
try {
sqlSession = sqlSessionFactory.openSession();
//namespace+id
sqlSession.insert("cn.jarjar.dao.BlogMapper.insertBlog", blog);
sqlSession.commit(true)
} catch (Exception e) {
e.printStackTrace();
sqlSession.rollback(true);
} finally {
sqlSession.close();
}
ä¹å°±æ¯è¦ååå§çjava.sql.Connection对象ä¸æ ·ï¼å¿ é¡»æç §ï¼æ°å»ºè¿æ¥->æ§è¡SQL->æ交ï¼æ¥è¯¢ä¸éè¦ï¼->å¦ææä½æ°æ®åå¨å¼å¸¸éè¦åæ»->éæ¾æ°æ®åºè¿æ¥ã注æ第ä¸ç¹åæåä¸ç¹ï¼æ¯ä¸ªSqlSessionæ°å»ºä¹åå¿ é¡»éæ¾ï¼ä¸ç¶ä¼é ææ°æ®åºè¿æ¥æ³é²çå±é©ãä¹å°±æ¯æå³çSqlSessionæ¯ä¸ªæç¶æç对象ï¼æ¯æ æ³è¿è¡å¤ç¨çï¼æ以åªè½å±éäºrequestæè æ¹æ³çèå´ï¼ä¹å°±æ¯æè°ç线ç¨ä¸å®å ¨ã
ç°è±¡2ï¼å¦æ使ç¨springéæmybatisï¼å®æ¹æä¾äºæ´åå mybatis-spring.jarï¼å¦æå®æé ç½®ä¹åï¼ä½¿ç¨æ¹å¼åå ¶ç®åï¼ç®å示ä¾å¦ä¸ï¼
//æ³¨å ¥springä¸é ç½®çSqlSessionTemplate对象ï¼åä¾
@Resource(name="sqlSessionTemplate")
public SqlSessionTemplate sqlSessionTemplate;
public void saveTestTrans(){
this.sqlSessionTemplate.selectList("testdomain.selectAnySql", "select * from my_blog where id='1'");
}
è¿éçSqlSessionTemplateä¸ä» æ¯åä¾çï¼èä¸ä¸éè¦æå·¥æ°å»ºåå ³éSqlSession
é®é¢1ï¼
é£ä¹é®é¢æ¥äºï¼ä¸ºä»ä¹mybatis-spring.jarä¸çSqlSessionTemplateå¯ä»¥è¢«å¤ä¸ªdaoå¤ç¨ï¼èä¸ä¸ä¼é ææ°æ®è¿æ¥æ³é²å¢ï¼å¹¶ä¸è¿å¯ä»¥èªå¨æ°å»ºåéæ¾æ°æ®åºè¿æ¥ï¼å®æ¹è§£çæ¯å 为SqlSessionTemplateæ¯çº¿ç¨å®å ¨çï¼ä¹å°±æ¯ç¡®ä¿æ¯ä¸ªçº¿ç¨ä½¿ç¨çsqlSessionçå¯ä¸å¹¶ä¸äºç¸å²çªã
é¦å çäºä¸ä¸mybatis-springçæºç ï¼åç°SqlSessionTemplateæ¯éè¿ä»£çæ¦æªåSqlSessionHolderå®ç°çsqlsession线ç¨å®å ¨åèªå¨æ°å»ºåéæ¾è¿æ¥çãçæé å½æ°å½æ°ä¸æ建代çç±»ï¼è¯¥ä»£çç±»å®ç°SqlSessionæ¥å£ï¼å®ä¹äºæ¹æ³æ¦æªå¨ï¼å¦æè°ç¨ä»£çç±»å®ä¾ä¸å®ç°SqlSessionæ¥å£å®ä¹çæ¹æ³ï¼è¯¥è°ç¨å被导åSqlSessionInterceptorçinvokeæ¹æ³ï¼è¿ä¸ªæ¹æ³ä¸èªå¨è¿è¡äºSqlSessionçèªå¨è¯·æ±åéæ¾ï¼å¦æä¸è¢«springæ管åèªå·±æ°å»ºåéæ¾sqlsessionï¼å¦æ被spring管çå使ç¨SqlSessionHolderè¿è¡requestårelaseæä½ï¼
以ä¸ç½åé对SqlSessionTemplateç线ç¨å®å ¨ç¹æ§è¿è¡äºè¯¦ç»çæ¢ç©¶ï¼blogs.com/daxin/p/.html
é®é¢2ï¼
ç¶ååæ³å°è¿æ ·ä¸ä¸ªé®é¢ï¼è½ç¶ç°å¨å ä¹ææ项ç®é½ä½¿ç¨springä½ä¸ºjavaç¨åºçåºæ¬æ¡æ¶ï¼å¦ææä¸ä½¿ç¨spring管çmybatisï¼ä» ä» ä½¿ç¨åå§çmybatisï¼æä¹æ ·æè½æ建ä¸ä¸ªåSqlSessionTemplateç¸ä¼¼ç对象å¢ï¼
é¦å æ³å°å¿ 须使ç¨javaçtreadLocalæ建ä¸ä¸ªsqlsessionç对象ï¼å¦ThreadLocal sqlSession = new ThreadLocal
()ã
ç»è¿æ¥æ¾ï¼åç°mybatisèªèº«å°±æè¿æ ·ä¸ä¸ªç±»å®ç°äºç±»ä¼¼çåè½ï¼ç±»è·¯å¾ï¼org.apache.ibatis.session.SqlSessionManagerï¼ä½æ¯æ²¡æ注éï¼å¯è½åå¨mybatis-springè¿ç§ç¥å¨ä¹åï¼mybatisæ¾å¼äºå¯¹è¿ä¸ªç±»çç»´æ¤ã
该类å®ç°äºSqlSessionFactory, SqlSession并ä¸å¨å ¶ä¸å®ä¹äºä¸ä¸ªtreadLocalçsqlssion对象ï¼åæ¶ä½¿ç¨äºä»£çæ¦æªè¿è¡äºsqlsessionçèªå¨ç®¡çï¼å ·ä½ä»£ç å¯ä»¥èªå·±æ¥é ï¼å¯¹äºç解mybatisåçåjavaç代çæºå¶å¾æ帮å©ã
é£ä¹å个ç®åçç¨åºéªè¯ä¸ä¸SqlSessionManageræ¯å¦ççå¯ä»¥ä¿è¯çº¿ç¨å®å ¨åèªå¨æ°å»ºåéæ¾sqlssionï¼TestSqlManager.java
private static SqlSession sqlSession;
public static SqlSession getSqlSessionTest(){
if(sqlSession == null){
//æ建使ç¨çSqlSessionFactory
SqlSessionFactory sqlSessionFactory = MyBatisUtil.getSqlSessionFactory();
sqlSession = SqlSessionManager.newInstance(sqlSessionFactory);
}
return sqlSession;
}
public static void main(String[] args) throws InterruptedException {
Run run = new Run();
List
threads = new ArrayList
();
for (int i = 0; i < ; i++) {
Thread t = new Thread(run);
threads.add(t);
System.out.println("thread:{ "+t.getName()+"}, start");
t.start();
}
for (Thread t : threads) {
System.out.println("thread:{ "+t.getName()+"},join");
t.join();
}
}
ææ¬æºè£ çmysqlï¼éè¿çæ§è¯å¥ï¼select SUBSTRING_INDEX(host,â:â,1) as ip , count(*) from information_schema.processlist group by ip;åç°æ§è¡è¿ç¨ä¸åå¨è¿æ¥å¹¶åçæ åµï¼ä½æ¯æ§è¡ä¹åå ¨é¨éæ¾æäºã
mybatis springä»ç»ã使ç¨ãå®ç°åç
mavenä¾èµ<dependency><groupId>org.mybatis</groupId><artifactId>mybatis-spring</artifactId><version>2.0.6</version></dependency>使ç¨
SqlSessionFactoryBean å¯ä»¥å建sqlSessionFactoryï¼dataSourceæ¯èªå·±çæ°æ®æºçbean @MapperScan注解å¯ä»¥å¸®å©æ们æMyBatisçMapper类注å为beanï¼è¿æ ·æ们就å¯ä»¥å¨ä½¿ç¨çå°æ¹éè¿@Autowired/@Resourceå¼ç¨æ¥ä½¿ç¨ã
@MapperScan("com.github.liuzhengyang")@ConfigurationpublicclassMyBatisConfig{ @Autowired@BeanpublicSqlSessionFactoryBeansqlSessionFactoryBean(DataSourcedataSource){ SqlSessionFactoryBeansqlSessionFactoryBean=newSqlSessionFactoryBean();sqlSessionFactoryBean.setDataSource(dataSource);returnsqlSessionFactoryBean;}}å®ç°åçmybatis-spring帮å©æ们ç®åçå·¥ä½ã带æ¥çä»·å¼æ¯
SqlSessionFactoryå建çå·¥ä½ï¼ä½¿ç¨åççmybatiséè¦ç¨é ç½®æ件é ç½®mybatisï¼mybais-springå¯ä»¥ç¨@Bean代ç å建ã(è½ç¶mybatisä¹è½ç¨ä»£ç æ建ï¼ä¸è¿SqlSessionFactory被spring管çäºï¼å¨ä½¿ç¨çæ¶ååªéè¦@Autowireä¼æ´æ¹ä¾¿)
ä¸åéè¦æ¯æ¬¡openSessionãcloseï¼è¿äºå·¥ä½å¨mybatis-springå é¨å®ç°äºï¼mybatis-spring帮å©æ们å¤ææ¯å¦è¦openSession
Mapperç±»åæäºbeanï¼éè¦ä½¿ç¨çæ¶åç´æ¥@Autowiredå°±å¯ä»¥
æä¾çº¿ç¨å®å ¨çSqlSessionTemplate
SqlSessionFactoryå¦ä½å建SqlSessionFactoryéè¿SqlSessionFactoryBean#buildSqlSessionFactoryæ建ï¼è°ç¨æ¶æºæ¯SqlSessionFactoryBean.afterPropertiesSetã SqlSessionFactoryæ大éå¯é 置项ï¼è¿äºé 置项æç»è½¬å为SqlSessionFactoryçæ建åæ°(Configuration)
@OverridepublicvoidafterPropertiesSet()throwsException{ notNull(dataSource,"Property'dataSource'isrequired");notNull(sqlSessionFactoryBuilder,"Property'sqlSessionFactoryBuilder'isrequired");state((configuration==null&&configLocation==null)||!(configuration!=null&&configLocation!=null),"Property'configuration'and'configLocation'cannotspecifiedwithtogether");this.sqlSessionFactory=buildSqlSessionFactory();}protectedSqlSessionFactorybuildSqlSessionFactory()throwsException{ finalConfigurationtargetConfiguration;...XMLConfigBuilderxmlConfigBuilder=null;if(this.configuration!=null){ targetConfiguration=this.configuration;if(targetConfiguration.getVariables()==null){ targetConfiguration.setVariables(this.configurationProperties);}elseif(this.configurationProperties!=null){ targetConfiguration.getVariables().putAll(this.configurationProperties);}}elseif(this.configLocation!=null){ xmlConfigBuilder=newXMLConfigBuilder(this.configLocation.getInputStream(),null,this.configurationProperties);targetConfiguration=xmlConfigBuilder.getConfiguration();}else{ LOGGER.debug(()->"Property'configuration'or'configLocation'notspecified,usingdefaultMyBatisConfiguration");targetConfiguration=newConfiguration();Optional.ofNullable(this.configurationProperties).ifPresent(targetConfiguration::setVariables);}...returnthis.sqlSessionFactoryBuilder.build(targetConfiguration);}Mapperç±»å¦ä½æ³¨åæbeanå°BeanFactoryä¸ç使ç¨äºmybatis-springï¼ä¼æ«æç¹å®çMapperç±»ï¼@MapperScan注解æ§å¶ï¼æ§å¶æ 注äºä»»æ注解çæ¥å£å¯ä»¥è¢«æ³¨åä¸ï¼è¿å¯ä»¥é ç½®æ¥å£çparentå¤æï¼ï¼ç¶åä½ä¸ºBean注åå°beanFactoryä¸ï¼ä»èè½è¢«å ¶ä»çbeanä¾èµä½¿ç¨ã
@MapperpublicinterfaceUserMapper{ UsergetUserById(longid);}è¦å®ç°è¿æ ·çscanæºå¶ï¼å°±éè¦ä¸ä¸ªscan mapperçBeanPostProcessorï¼è¿ä¸ªprocessorä¸ï¼scanå½åclasspathä¸æ»¡è¶³MapperScané ç½®çpackageè¦æ±çç±»ï¼æ¥å£ï¼ï¼å¹¶ä¸å¤ææ¯å¦æ@Mapper注解ï¼å¦æ符åï¼å建BeanDefinition注åå°BeanFactoryä¸ãå¨getBeançæ¶åï¼è°ç¨MapperFactoryBean.getObjectæ¿å°çMapper代çï¼å®ç°æ¯Configuration.getMapper(Class type, SqlSession sqlSession), SqlSessionæ¯SqlSessionTemplateèªèº«ãæåå¨afterPropertiesSetï¼ä¼æ¿å°SqlSessionFactory.getConfiguration()ï¼è°ç¨addMapper(Class type)æ·»å å°mybatisä¸
为ä»ä¹å¢å äº@MapperScan注解ï¼å°±è½æ«æ注åMapperäºå¢ãä»MapperScanç±»å¯ä»¥çå°ï¼ä¸é¢æä¸ä¸ª@Import注解ï¼importäºMapperScannerRegistrar
@Import(MapperScannerRegistrar.class)@Repeatable(MapperScans.class)public@interfaceMapperScan{ ...}springç@Import注解ä¸è¬ç¨æ¥å¼ç¨å ¶ä»çConfigurationï¼è¿å¯ä»¥å¼ç¨ ImportSelectoråImportBeanDefinitionRegistrar å®ç°æå ¶ä»çComponentç±»ã
Provides functionality equivalent to the element in Spring XML. Allows for importing @Configuration classes, ImportSelector and ImportBeanDefinitionRegistrar implementations, as well as regular component classes (as of 4.2; analogous to AnnotationConfigApplicationContext.register).
æ»ä¹ï¼çä»·äºå£°æäºä¸ä¸ªMapperScannerRegistrar Beanãæ们çä¸ä¸MapperScannerRegistrarçå®ç°ï¼MapperScannerRegistratå®ç°äºImportBeanDefinitionRegistraråResourceLoaderAwareæ¥å£ã
ImportBeanDefinitionRegistraræ¥å£ï¼ç¨æ¥å¨å¤ç@Configurationç±»çæ¶åï¼å建bean definition级å«çbeanã
Interface to be implemented by types that register additional bean definitions when processing @Configuration classes. Useful when operating at the bean definition level (as opposed to @Bean method/instance level) is desired or necessary.
å¨springçrefreshé¶æ®µï¼æä¸æ¥æ¯invokeBeanFactoryPostProcessorsï¼ä¼è°ç¨å°ConfigurationClassPostProcessor.postProcessBeanDefinitionRegistryï¼æç»ä¼è°ç¨å°loadBeanDefinitionsFromRegistrarsï¼è°ç¨å°MapperScannerRegistrar.registerBeanDefinitions
@OverridepublicvoidpostProcessBeanDefinitionRegistry(BeanDefinitionRegistryregistry){ intregistryId=System.identityHashCode(registry);if(this.registriesPostProcessed.contains(registryId)){ thrownewIllegalStateException("postProcessBeanDefinitionRegistryalreadycalledonthispost-processoragainst"+registry);}if(this.factoriesPostProcessed.contains(registryId)){ thrownewIllegalStateException("postProcessBeanFactoryalreadycalledonthispost-processoragainst"+registry);}this.registriesPostProcessed.add(registryId);processConfigBeanDefinitions(registry);}privatevoidloadBeanDefinitionsForConfigurationClass(ConfigurationClassconfigClass,TrackedConditionEvaluatortrackedConditionEvaluator){ if(trackedConditionEvaluator.shouldSkip(configClass)){ StringbeanName=configClass.getBeanName();if(StringUtils.hasLength(beanName)&&this.registry.containsBeanDefinition(beanName)){ this.registry.removeBeanDefinition(beanName);}this.importRegistry.removeImportingClass(configClass.getMetadata().getClassName());return;}if(configClass.isImported()){ registerBeanDefinitionForImportedConfigurationClass(configClass);}for(BeanMethodbeanMethod:configClass.getBeanMethods()){ loadBeanDefinitionsForBeanMethod(beanMethod);}loadBeanDefinitionsFromImportedResources(configClass.getImportedResources());loadBeanDefinitionsFromRegistrars(configClass.getImportBeanDefinitionRegistrars());}privatevoidloadBeanDefinitionsFromRegistrars(Map<ImportBeanDefinitionRegistrar,AnnotationMetadata>registrars){ registrars.forEach((registrar,metadata)->registrar.registerBeanDefinitions(metadata,this.registry));}åçä¸ä¸MapperScannerRegistrarçå®ç°ãregisterBeanDefinitionså建äºä¸ä¸ªBeanDefinitionï¼beanæ¯MapperScannerConfigurerï¼é ç½®äºMapperScannerConfigureréè¦çå±æ§é ç½®ï¼é ç½®æ¥æºäº@MapperScan注解)ï¼ä¾å¦annotationClass, factoryBeançã
publicclassMapperScannerRegistrarimplementsImportBeanDefinitionRegistrar,ResourceLoaderAware{ @OverridepublicvoidregisterBeanDefinitions(AnnotationMetadataimportingClassMetadata,BeanDefinitionRegistryregistry){ AnnotationAttributesmapperScanAttrs=AnnotationAttributes.fromMap(importingClassMetadata.getAnnotationAttributes(MapperScan.class.getName()));if(mapperScanAttrs!=null){ registerBeanDefinitions(importingClassMetadata,mapperScanAttrs,registry,generateBaseBeanName(importingClassMetadata,0));}}voidregisterBeanDefinitions(AnnotationMetadataannoMeta,AnnotationAttributesannoAttrs,BeanDefinitionRegistryregistry,StringbeanName){ BeanDefinitionBuilderbuilder=BeanDefinitionBuilder.genericBeanDefinition(MapperScannerConfigurer.class);builder.addPropertyValue("processPropertyPlaceHolders",true);Class<?extendsAnnotation>annotationClass=annoAttrs.getClass("annotationClass");if(!Annotation.class.equals(annotationClass)){ builder.addPropertyValue("annotationClass",annotationClass);}Class<?>markerInterface=annoAttrs.getClass("markerInterface");if(!Class.class.equals(markerInterface)){ builder.addPropertyValue("markerInterface",markerInterface);}Class<?extendsBeanNameGenerator>generatorClass=annoAttrs.getClass("nameGenerator");if(!BeanNameGenerator.class.equals(generatorClass)){ builder.addPropertyValue("nameGenerator",BeanUtils.instantiateClass(generatorClass));}Class<?extendsMapperFactoryBean>mapperFactoryBeanClass=annoAttrs.getClass("factoryBean");if(!MapperFactoryBean.class.equals(mapperFactoryBeanClass)){ builder.addPropertyValue("mapperFactoryBeanClass",mapperFactoryBeanClass);}StringsqlSessionTemplateRef=annoAttrs.getString("sqlSessionTemplateRef");if(StringUtils.hasText(sqlSessionTemplateRef)){ builder.addPropertyValue("sqlSessionTemplateBeanName",annoAttrs.getString("sqlSessionTemplateRef"));}StringsqlSessionFactoryRef=annoAttrs.getString("sqlSessionFactoryRef");if(StringUtils.hasText(sqlSessionFactoryRef)){ builder.addPropertyValue("sqlSessionFactoryBeanName",annoAttrs.getString("sqlSessionFactoryRef"));}List<String>basePackages=newArrayList<>();basePackages.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()));if(basePackages.isEmpty()){ basePackages.add(getDefaultBasePackage(annoMeta));}StringlazyInitialization=annoAttrs.getString("lazyInitialization");if(StringUtils.hasText(lazyInitialization)){ builder.addPropertyValue("lazyInitialization",lazyInitialization);}StringdefaultScope=annoAttrs.getString("defaultScope");if(!AbstractBeanDefinition.SCOPE_DEFAULT.equals(defaultScope)){ builder.addPropertyValue("defaultScope",defaultScope);}builder.addPropertyValue("basePackage",StringUtils.collectionToCommaDelimitedString(basePackages));registry.registerBeanDefinition(beanName,builder.getBeanDefinition());}privatestaticStringgenerateBaseBeanName(AnnotationMetadataimportingClassMetadata,intindex){ returnimportingClassMetadata.getClassName()+"#"+MapperScannerRegistrar.class.g