Springboot下Mybatis源码
1.使用
dependencies { compile 'mysql:mysql-connector-java:8.0.22' compile 'org.mybatis.spring.boot:mybatis-spring-boot-starter:2.1.3' }
2.启动加载
SPI机制:
配置类加载时机:
public void refresh() throws BeansException, IllegalStateException { synchronized(this.startupShutdownMonitor) { //准备工作,记录容器的启动时间、标记“已启动”状态、检查环境变量等 prepareRefresh(); //创建一个默认的BeanFactory: DefaultListableBeanFactory,并加载BeanDefinition ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); /*对Bean工厂进行属性填充: 1.设置类加载器,bean表达式解释器,忽略给定接口的自动装配功能 2.添加了ApplicationContextAwareProcessor(获取 applicationContext上下文,资源,系统参数等) ApplicationListenerDetector后置处理器(检测容器中的ApplicationLisenter,将其注册到上下文中)*/ prepareBeanFactory(beanFactory); try { //目前没有任何实现 postProcessBeanFactory(beanFactory); /* 拿到所有自定义和内置的BeanDefinitionRegistryPostProcessor后置处理器,循环调用postProcessBeanDefinitionRegistry; 其中最重要的是ConfigurationClassPostProcessor处理器的执行:遍历BeanDefinition找到带有@Configuration注解的BeanDefinition, 解析处理配置类中的@Import,@PropertySources,@ComponentScans(如果存在注解,则会扫描对应路径的类转换成BeanDefinition,存入BeanDefinitionMap),@Bean(同样)注解等 */ invokeBeanFactoryPostProcessors(beanFactory); //注册BeanPostProcessor后置处理器 registerBeanPostProcessors(beanFactory); //初始化消息资源解析器 initMessageSource(); //初始化注册一个单列ApplicationContext事件监听器applicationEventMulticaster initApplicationEventMulticaster(); //容器初始化扩展方法,交给子类实现 onRefresh(); //注册事件监听器,派发容器初始化的事件:监听器需要实现ApplicationListener接口 registerListeners(); //实例所有的单例Bean,创建单例非懒加载的bean finishBeanFactoryInitialization(beanFactory); //容器初始化完成 finishRefresh(); } catch (BeansException var9) { if (logger.isWarnEnabled()) { logger.warn("Exception encountered during context initialization - cancelling refresh attempt: " + var9); } destroyBeans(); cancelRefresh(var9); throw var9; } finally { resetCommonCaches(); } } }
protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) { // 获取容器中的BeanFactoryPostProcessor(注意这里自定义的BeanFactoryPostProcessor还没有初始化) // getBeanFactoryPostProcessors()方法一般是获取不到值的,除非我们手动调用addBeanFactoryPostProcessor方法或注解@Component来注入BeanFactoryPostProcessors对象 // 重点关注ConfigurationClassPostProcessor PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, this.getBeanFactoryPostProcessors()); if (beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) { beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory)); beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader())); } }
PostProcessorRegistrationDelegate类下:
public static void invokeBeanFactoryPostProcessors( ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) { Set<String> processedBeans = new HashSet<>(); //开始处理BeanDefinitionRegistryPostProcessor // 判断beanFactory是否为BeanDefinitionRegistry,beanFactory为DefaultListableBeanFactory,而DefaultListableBeanFactory实现了BeanDefinitionRegistry接口,因此为true if (beanFactory instanceof BeanDefinitionRegistry) { BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory; // 用于存放普通的BeanFactoryPostProcessor List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>(); // 用于存放BeanDefinitionRegistryPostProcessor List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>(); // 首先处理入参中的beanFactoryPostProcessors,遍历区分BeanDefinitionRegistryPostProcessor和普通BeanFactoryPostProcessor for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) { if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) { BeanDefinitionRegistryPostProcessor registryProcessor = (BeanDefinitionRegistryPostProcessor) postProcessor; // 执行BeanDefinitionRegistryPostProcessor接口的postProcessBeanDefinitionRegistry方法 registryProcessor.postProcessBeanDefinitionRegistry(registry); // 添加到registryProcessors(用于最后执行postProcessBeanFactory方法) registryProcessors.add(registryProcessor); }else { // 添加到regularPostProcessors(用于最后执行postProcessBeanFactory方法) regularPostProcessors.add(postProcessor); } } // 首先,调用实现PriorityOrdered的BeanDefinitionRegistryPostProcessors // 用于保存本次要执行的BeanDefinitionRegistryPostProcessor。 List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>(); // 找出所有实现BeanDefinitionRegistryPostProcessor接口的Bean的beanName String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false); for (String ppName : postProcessorNames) { // 校验是否实现了PriorityOrdered接口 if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) { currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class)); processedBeans.add(ppName); } } // 进行排序(根据是否实现PriorityOrdered、Ordered接口和order值来排序) sortPostProcessors(currentRegistryProcessors, beanFactory); // 合并 registryProcessors.addAll(currentRegistryProcessors); // 遍历currentRegistryProcessors, 执行postProcessBeanDefinitionRegistry方法 invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry); // 清空currentRegistryProcessors currentRegistryProcessors.clear(); ...省略 } ...省略 }
原因:
public class ConfigurationClassPostProcessor implements BeanDefinitionRegistryPostProcessor, PriorityOrdered, ResourceLoaderAware, BeanClassLoaderAware, EnvironmentAware {...}
ConfigurationClassPostProcessor类下加载所有的配置文件,包括spring.factories文件中的:
@Override public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) { ...省略 // 执行postProcessBeanDefinitionRegistry方法 processConfigBeanDefinitions(registry); } public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) { List<BeanDefinitionHolder> configCandidates = new ArrayList<>(); // 获取Spring容器中目前所有BeanDefinition的名称 String[] candidateNames = registry.getBeanDefinitionNames(); // 遍历判断是否有没有解析过 for (String beanName : candidateNames) { BeanDefinition beanDef = registry.getBeanDefinition(beanName); if (beanDef.getAttribute(ConfigurationClassUtils.CONFIGURATION_CLASS_ATTRIBUTE) != null) { if (logger.isDebugEnabled()) { logger.debug("Bean definition has already been processed as a configuration class: " + beanDef); } } // 判断是否是配置类 else if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)) { configCandidates.add(new BeanDefinitionHolder(beanDef, beanName)); } } // 如果未找到@Configuration类,则立即返回 if (configCandidates.isEmpty()) { return; } // 按@Order值排序 configCandidates.sort((bd1, bd2) -> { int i1 = ConfigurationClassUtils.getOrder(bd1.getBeanDefinition()); int i2 = ConfigurationClassUtils.getOrder(bd2.getBeanDefinition()); return Integer.compare(i1, i2); }); // 创建@CompentScan、@Import导入进来的bean名称的生成器 SingletonBeanRegistry sbr = null; if (registry instanceof SingletonBeanRegistry) { sbr = (SingletonBeanRegistry) registry; if (!this.localBeanNameGeneratorSet) { BeanNameGenerator generator = (BeanNameGenerator) sbr.getSingleton( AnnotationConfigUtils.CONFIGURATION_BEAN_NAME_GENERATOR); if (generator != null) { this.componentScanBeanNameGenerator = generator; this.importBeanNameGenerator = generator; } } } // 如果系统环境为空则构建系统环境 if (this.environment == null) { this.environment = new StandardEnvironment(); } // 解析每个@Configuration类 ConfigurationClassParser parser = new ConfigurationClassParser( this.metadataReaderFactory, this.problemReporter, this.environment, this.resourceLoader, this.componentScanBeanNameGenerator, registry); // 创建一个集合用于保存我们的配置类BeanDefinitionHolder集合默认长度是配置类集合的长度 Set<BeanDefinitionHolder> candidates = new LinkedHashSet<>(configCandidates); // 创建一个集合用于保存我们的已经解析的配置类,长度默认为解析出来默认的配置类的集合长度 Set<ConfigurationClass> alreadyParsed = new HashSet<>(configCandidates.size()); do { // 真正的解析我们的配置类 parser.parse(candidates); parser.validate(); // 解析出来的配置类 Set<ConfigurationClass> configClasses = new LinkedHashSet<>(parser.getConfigurationClasses()); configClasses.removeAll(alreadyParsed); // Read the model and create bean definitions based on its content if (this.reader == null) { this.reader = new ConfigurationClassBeanDefinitionReader( registry, this.sourceExtractor, this.resourceLoader, this.environment, this.importBeanNameGenerator, parser.getImportRegistry()); } // 在此之前仅仅只是解析完成,并未注册到Spring容器中,然后将解析出来的配置类转换成BeanDefinition并注册到Spring 容器中
// 在这里加载 配置文件中的关联的其他 后置处理器或资源
// MapperScannerConfigurer、SqlSessionFactoryBean就是在这里注册到容器中的
this.reader.loadBeanDefinitions(configClasses); alreadyParsed.addAll(configClasses); candidates.clear(); //判断 Spring 容器中Bean的定义数量是否 > 候选原始的bean定义的个数 if (registry.getBeanDefinitionCount() > candidateNames.length) { // 获取所有的bean定义 String[] newCandidateNames = registry.getBeanDefinitionNames(); // 原始的bean定义 Set<String> oldCandidateNames = new HashSet<>(Arrays.asList(candidateNames)); Set<String> alreadyParsedClasses = new HashSet<>(); // 赋值已经解析的 for (ConfigurationClass configurationClass : alreadyParsed) { alreadyParsedClasses.add(configurationClass.getMetadata().getClassName()); } // 判断是否有漏掉没有解析的配置类 for (String candidateName : newCandidateNames) { if (!oldCandidateNames.contains(candidateName)) { BeanDefinition bd = registry.getBeanDefinition(candidateName); if (ConfigurationClassUtils.checkConfigurationClassCandidate(bd, this.metadataReaderFactory) && !alreadyParsedClasses.contains(bd.getBeanClassName())) { candidates.add(new BeanDefinitionHolder(bd, candidateName)); } } } candidateNames = newCandidateNames; } } // 循环解析 while (!candidates.isEmpty()); // 将ImportRegistry注册为Bean,以支持ImportAware @Configuration类 if (sbr != null && !sbr.containsSingleton(IMPORT_REGISTRY_BEAN_NAME)) { sbr.registerSingleton(IMPORT_REGISTRY_BEAN_NAME, parser.getImportRegistry()); } // 清除缓存 if (this.metadataReaderFactory instanceof CachingMetadataReaderFactory) { ((CachingMetadataReaderFactory) this.metadataReaderFactory).clearCache(); } } public void parse(Set<BeanDefinitionHolder> configCandidates) { for (BeanDefinitionHolder holder : configCandidates) { BeanDefinition bd = holder.getBeanDefinition(); try { if (bd instanceof AnnotatedBeanDefinition) { // 如果bean实现自 AnnotatedBeanDefinition 接口,则进行注解bean定义的解析 parse(((AnnotatedBeanDefinition) bd).getMetadata(), holder.getBeanName()); } else if (bd instanceof AbstractBeanDefinition && ((AbstractBeanDefinition) bd).hasBeanClass()) { // 如果bean实现自 AbstractBeanDefinition 接口,则进行抽象bean定义的解析 parse(((AbstractBeanDefinition) bd).getBeanClass(), holder.getBeanName()); } else { // 常规配置类进行解析 parse(bd.getBeanClassName(), holder.getBeanName()); } } ... } //这里会加载解析spring.properties中的配置类 this.deferredImportSelectorHandler.process(); } public void process() { List<DeferredImportSelectorHolder> deferredImports = this.deferredImportSelectors; this.deferredImportSelectors = null; try { if (deferredImports != null) { DeferredImportSelectorGroupingHandler handler = new DeferredImportSelectorGroupingHandler(); deferredImports.sort(DEFERRED_IMPORT_COMPARATOR); deferredImports.forEach(handler::register); handler.processGroupImports(); } } finally { this.deferredImportSelectors = new ArrayList<>(); } } public void processGroupImports() { for (DeferredImportSelectorGrouping grouping : this.groupings.values()) { Predicate<String> exclusionFilter = grouping.getCandidateFilter(); grouping.getImports().forEach(entry -> { ConfigurationClass configurationClass = this.configurationClasses.get(entry.getMetadata()); try { processImports(configurationClass, asSourceClass(configurationClass, exclusionFilter), Collections.singleton(asSourceClass(entry.getImportClassName(), exclusionFilter)), exclusionFilter, false); } ... }); } } public Iterable<Group.Entry> getImports() { for (DeferredImportSelectorHolder deferredImport : this.deferredImports) { this.group.process(deferredImport.getConfigurationClass().getMetadata(), deferredImport.getImportSelector()); } return this.group.selectImports(); } public void process(AnnotationMetadata annotationMetadata, DeferredImportSelector deferredImportSelector) { Assert.state(deferredImportSelector instanceof AutoConfigurationImportSelector, () -> String.format("Only %s implementations are supported, got %s", AutoConfigurationImportSelector.class.getSimpleName(), deferredImportSelector.getClass().getName())); AutoConfigurationEntry autoConfigurationEntry = ((AutoConfigurationImportSelector) deferredImportSelector) .getAutoConfigurationEntry(annotationMetadata); this.autoConfigurationEntries.add(autoConfigurationEntry); for (String importClassName : autoConfigurationEntry.getConfigurations()) { this.entries.putIfAbsent(importClassName, annotationMetadata); } } protected AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) { if (!isEnabled(annotationMetadata)) { return EMPTY_ENTRY; } AnnotationAttributes attributes = getAttributes(annotationMetadata); List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes); configurations = removeDuplicates(configurations); Set<String> exclusions = getExclusions(annotationMetadata, attributes); checkExcludedClasses(configurations, exclusions); configurations.removeAll(exclusions); configurations = getConfigurationClassFilter().filter(configurations); fireAutoConfigurationImportEvents(configurations, exclusions); return new AutoConfigurationEntry(configurations, exclusions); } protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) { List<String> configurations = SpringFactoriesLoader.loadFactoryNames(getSpringFactoriesLoaderFactoryClass(), getBeanClassLoader()); Assert.notEmpty(configurations, "No auto configuration classes found in META-INF/spring.factories. If you " + "are using a custom packaging, make sure that file is correct."); return configurations; } public static List<String> loadFactoryNames(Class<?> factoryType, @Nullable ClassLoader classLoader) { String factoryTypeName = factoryType.getName(); return loadSpringFactories(classLoader).getOrDefault(factoryTypeName, Collections.emptyList()); }
Mapper加载时机:
1.先加载扫描Mapper的后置处理器
public class MapperScannerConfigurer implements BeanDefinitionRegistryPostProcessor, InitializingBean, ApplicationContextAware, BeanNameAware {...}
...省略 // 解析配置类 parser.parse(candidates); parser.validate(); // 解析出来的配置类 Set<ConfigurationClass> configClasses = new LinkedHashSet<>(parser.getConfigurationClasses()); configClasses.removeAll(alreadyParsed); // Read the model and create bean definitions based on its content if (this.reader == null) { this.reader = new ConfigurationClassBeanDefinitionReader( registry, this.sourceExtractor, this.resourceLoader, this.environment, this.importBeanNameGenerator, parser.getImportRegistry()); } // 在此之前仅仅只是解析完成,并未注册到Spring容器中,然后将解析出来的配置类转换成BeanDefinition并注册到Spring 容器中 // 在这里加载 配置文件中的关联的其他 后置处理器或资源 // MapperScannerConfigurer后置处理器就是在这里注册到容器中的 this.reader.loadBeanDefinitions(configClasses); ...省略
注意:此时MapperScannerConfigurer注册完成时
PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());
并未执行结束,因为当前还处在执行BeanDefinitionRegistryPostProcessor优先级PriorityOrdered 的ConfigurationClassPostProcessor中。
2.扫描加了@Mapper注解的类,将之注册到BeanDefinitionMap中
继续处理 MapperScannerConfigurer 后置处理器
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.setMapperFactoryBeanClass(this.mapperFactoryBeanClass); if (StringUtils.hasText(lazyInitialization)) { scanner.setLazyInitialization(Boolean.valueOf(lazyInitialization)); } scanner.registerFilters(); scanner.scan( StringUtils.tokenizeToStringArray(this.basePackage, ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS)); } public int scan(String... basePackages) { int beanCountAtScanStart = this.registry.getBeanDefinitionCount(); // 开始进行包扫描 doScan(basePackages); // 注册注释配置处理器,如果有需要(再次执行,将自定义的处理器也注册进容器) if (this.includeAnnotationConfig) { AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry); } return (this.registry.getBeanDefinitionCount() - beanCountAtScanStart); } 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 { processBeanDefinitions(beanDefinitions); } return beanDefinitions; } protected Set<BeanDefinitionHolder> doScan(String... basePackages) { Assert.notEmpty(basePackages, "At least one base package must be specified"); Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet<>(); for (String basePackage : basePackages) { Set<BeanDefinition> candidates = findCandidateComponents(basePackage); for (BeanDefinition candidate : candidates) { ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate); candidate.setScope(scopeMetadata.getScopeName()); String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry); if (candidate instanceof AbstractBeanDefinition) { postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName); } if (candidate instanceof AnnotatedBeanDefinition) { AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate); } if (checkCandidate(beanName, candidate)) { BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName); definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry); beanDefinitions.add(definitionHolder); registerBeanDefinition(definitionHolder, this.registry); } } } return 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"); definition.getConstructorArgumentValues().addGenericArgumentValue(beanClassName); // issue #59 //设置BeanClass为mapperFactoryBeanClass,在创建bean时会根据BeanClass和构造方法进行创建 // MapperFactoryBean是一个FactoryBean,使用FactoryBean可以得到一个Mapper的代理对象。 definition.setBeanClass(this.mapperFactoryBeanClass); 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) { LOGGER.debug(() -> "Enabling autowire by type for MapperFactoryBean with name '" + holder.getBeanName() + "'."); // 设置自动注入类型 definition.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_BY_TYPE); } definition.setLazyInit(lazyInitialization); } }
SqlSessionFactory
SqlSessionFactory创建时会去加载Mapper.xml文件
@Bean @ConditionalOnMissingBean public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception { SqlSessionFactoryBean factory = new SqlSessionFactoryBean(); factory.setDataSource(dataSource); factory.setVfs(SpringBootVFS.class); // 获取配置文件中mybatis配置文件的路径 if (StringUtils.hasText(this.properties.getConfigLocation())) { factory.setConfigLocation(this.resourceLoader.getResource(this.properties.getConfigLocation())); } applyConfiguration(factory); ...省略 if (!ObjectUtils.isEmpty(this.properties.resolveMapperLocations())) { factory.setMapperLocations(this.properties.resolveMapperLocations()); } ...省略 return factory.getObject(); } @Override public SqlSessionFactory getObject() throws Exception { // 不存在则创建 if (this.sqlSessionFactory == null) { afterPropertiesSet(); } return this.sqlSessionFactory; } @Override public void afterPropertiesSet() throws Exception { notNull(dataSource, "Property 'dataSource' is required"); notNull(sqlSessionFactoryBuilder, "Property 'sqlSessionFactoryBuilder' is required"); state((configuration == null && configLocation == null) || !(configuration != null && configLocation != null), "Property 'configuration' and 'configLocation' can not specified with together"); // 创建SqlSessionFactory this.sqlSessionFactory = buildSqlSessionFactory(); } protected SqlSessionFactory buildSqlSessionFactory() throws Exception { final Configuration targetConfiguration; ...省略 if (this.mapperLocations != null) { if (this.mapperLocations.length == 0) { LOGGER.warn(() -> "Property 'mapperLocations' was specified but matching resources are not found."); } else { // 遍历解析Mappper文件 for (Resource mapperLocation : this.mapperLocations) { if (mapperLocation == null) { continue; } try { XMLMapperBuilder xmlMapperBuilder = new XMLMapperBuilder(mapperLocation.getInputStream(), targetConfiguration, mapperLocation.toString(), targetConfiguration.getSqlFragments()); xmlMapperBuilder.parse(); } catch (Exception e) { throw new NestedIOException("Failed to parse mapping resource: '" + mapperLocation + "'", e); } finally { ErrorContext.instance().reset(); } LOGGER.debug(() -> "Parsed mapper file: '" + mapperLocation + "'"); } } } else { LOGGER.debug(() -> "Property 'mapperLocations' was not specified."); } return this.sqlSessionFactoryBuilder.build(targetConfiguration); }
public void parse() { // 是否已经解析 if (!configuration.isResourceLoaded(resource)) { // 解析mapper文件,从mapper节点开始 configurationElement(parser.evalNode("/mapper")); // 添加到已解析列表 configuration.addLoadedResource(resource); // 绑定mapper的namespace bindMapperForNamespace(); } parsePendingResultMaps(); parsePendingCacheRefs(); parsePendingStatements(); } private void configurationElement(XNode context) { try { String namespace = context.getStringAttribute("namespace"); if (namespace == null || namespace.isEmpty()) { throw new BuilderException("Mapper's namespace cannot be empty"); } // 设置namespace builderAssistant.setCurrentNamespace(namespace); // 解析parameterMap、resultMap、sql等节点 cacheRefElement(context.evalNode("cache-ref")); cacheElement(context.evalNode("cache")); parameterMapElement(context.evalNodes("/mapper/parameterMap")); resultMapElements(context.evalNodes("/mapper/resultMap")); sqlElement(context.evalNodes("/mapper/sql")); // 解析增删改查节点,并封装成Statement buildStatementFromContext(context.evalNodes("select|insert|update|delete")); } catch (Exception e) { throw new BuilderException("Error parsing Mapper XML. The XML location is '" + resource + "'. Cause: " + e, e); } } private void buildStatementFromContext(List<XNode> list) { if (configuration.getDatabaseId() != null) { buildStatementFromContext(list, configuration.getDatabaseId()); } buildStatementFromContext(list, null); } private void buildStatementFromContext(List<XNode> list, String requiredDatabaseId) { for (XNode context : list) { final XMLStatementBuilder statementParser = new XMLStatementBuilder(configuration, builderAssistant, context, requiredDatabaseId); try { // 解析节点 statementParser.parseStatementNode(); } catch (IncompleteElementException e) { configuration.addIncompleteStatement(statementParser); } } } public void parseStatementNode() { String id = context.getStringAttribute("id"); String databaseId = context.getStringAttribute("databaseId"); if (!databaseIdMatchesCurrent(id, databaseId, this.requiredDatabaseId)) { return; } String nodeName = context.getNode().getNodeName(); SqlCommandType sqlCommandType = SqlCommandType.valueOf(nodeName.toUpperCase(Locale.ENGLISH)); boolean isSelect = sqlCommandType == SqlCommandType.SELECT; boolean flushCache = context.getBooleanAttribute("flushCache", !isSelect); boolean useCache = context.getBooleanAttribute("useCache", isSelect); boolean resultOrdered = context.getBooleanAttribute("resultOrdered", false); // Include Fragments before parsing XMLIncludeTransformer includeParser = new XMLIncludeTransformer(configuration, builderAssistant); includeParser.applyIncludes(context.getNode()); String parameterType = context.getStringAttribute("parameterType"); Class<?> parameterTypeClass = resolveClass(parameterType); String lang = context.getStringAttribute("lang"); LanguageDriver langDriver = getLanguageDriver(lang); // Parse selectKey after includes and remove them. processSelectKeyNodes(id, parameterTypeClass, langDriver); // Parse the SQL (pre: <selectKey> and <include> were parsed and removed) KeyGenerator keyGenerator; String keyStatementId = id + SelectKeyGenerator.SELECT_KEY_SUFFIX; keyStatementId = builderAssistant.applyCurrentNamespace(keyStatementId, true); if (configuration.hasKeyGenerator(keyStatementId)) { keyGenerator = configuration.getKeyGenerator(keyStatementId); } else { keyGenerator = context.getBooleanAttribute("useGeneratedKeys", configuration.isUseGeneratedKeys() && SqlCommandType.INSERT.equals(sqlCommandType)) ? Jdbc3KeyGenerator.INSTANCE : NoKeyGenerator.INSTANCE; } SqlSource sqlSource = langDriver.createSqlSource(configuration, context, parameterTypeClass); StatementType statementType = StatementType.valueOf(context.getStringAttribute("statementType", StatementType.PREPARED.toString())); Integer fetchSize = context.getIntAttribute("fetchSize"); Integer timeout = context.getIntAttribute("timeout"); String parameterMap = context.getStringAttribute("parameterMap"); String resultType = context.getStringAttribute("resultType"); Class<?> resultTypeClass = resolveClass(resultType); String resultMap = context.getStringAttribute("resultMap"); String resultSetType = context.getStringAttribute("resultSetType"); ResultSetType resultSetTypeEnum = resolveResultSetType(resultSetType); if (resultSetTypeEnum == null) { resultSetTypeEnum = configuration.getDefaultResultSetType(); } String keyProperty = context.getStringAttribute("keyProperty"); String keyColumn = context.getStringAttribute("keyColumn"); String resultSets = context.getStringAttribute("resultSets"); builderAssistant.addMappedStatement(id, sqlSource, statementType, sqlCommandType, fetchSize, timeout, parameterMap, parameterTypeClass, resultMap, resultTypeClass, resultSetTypeEnum, flushCache, useCache, resultOrdered, keyGenerator, keyProperty, keyColumn, databaseId, langDriver, resultSets); }
private void bindMapperForNamespace() { // 获取当前解析的Namespace String namespace = builderAssistant.getCurrentNamespace(); if (namespace != null) { Class<?> boundType = null; try { boundType = Resources.classForName(namespace); } catch (ClassNotFoundException e) { // ignore, bound type is not required } if (boundType != null && !configuration.hasMapper(boundType)) { // 将 mapper的namespace绑定到指定接口 configuration.addLoadedResource("namespace:" + namespace); configuration.addMapper(boundType); } } }
加载总结:
1.在invokeBeanFactoryPostProcessors(beanFactory)方法中执行ConfigurationClassPostProcessor处理器的postProcessBeanDefinitionRegistry方法来解析配置类(spring.factories中的配置类);
2.this.reader.loadBeanDefinitions(configClasses)中加载配置类中所有的Bean Definitions信息(此时MybatisAutoConfiguration注册MapperScannerConfigurer处理器),以及sqlSessionFactory的Bean Definition;
3.执行MapperScannerConfigurer处理器的postProcessBeanDefinitionRegistry来扫描@Mapper接口并将之转化成MapperFactoryBean的Bean Definition;
4.在finishBeanFactoryInitialization(beanFactory)方法下的beanFactory.preInstantiateSingletons()实例化sqlSessionFactory时去解析Mapper.xml文件将之封装成MappedStatement对象
MapperScannerConfigurer