1. <!-- mybatis文件配置,扫描所有mapper文件 -->
    <!--SqlSessionFactoryBean的初始化参数-->
  1. <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
  2. <property name="dataSource" ref="dataSource"/>
  3. <property name="configLocation" value="classpath:/spring/mybatis.xml"/>
  4.  
  5. <property name="typeAliasesPackage" value="com.cloudwalk.shark.model"/>
  6.  
  7. <property name="mapperLocations" value="classpath*:mapper/*.xml"/>
  8. <property name="plugins">
  9. <array>
  10. <bean class="com.github.pagehelper.PageHelper">
  11. <property name="properties">
  12. <!--使用下面的方式配置参数,一行配置一个 -->
  13. <value>
  14. dialect=mysql
  15. </value>
  16. </property>
  17. </bean>
  18. </array>
  19. </property>
  20. </bean>
  1. <!-- spring与mybatis整合配置,扫描所有dao,指定的映射器类是接口,接口方法可以用注解来指定 SQL 语句,但是 MyBatis 的映射器 XML 文件也可以用。 -->
  2. <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"
  3. p:basePackage="com.cloudwalk.shark.mapper"
  4. p:sqlSessionFactoryBeanName="sqlSessionFactory"/>

下面跟踪SqlSessionFactoryBean.java的源码

  1. public class SqlSessionFactoryBean implements FactoryBean<SqlSessionFactory>, InitializingBean, ApplicationListener<ApplicationEvent> {
  2. }

实现了InitializingBean,ApplicationListener,自然而然就会在Spring加载的过程中做一些操作:

  1. public void afterPropertiesSet() throws Exception {
  2. Assert.notNull(this.dataSource, "Property 'dataSource' is required");
  3. Assert.notNull(this.sqlSessionFactoryBuilder, "Property 'sqlSessionFactoryBuilder' is required");
  4. Assert.state(this.configuration == null && this.configLocation == null || this.configuration == null || this.configLocation == null, "Property 'configuration' and 'configLocation' can not specified with together");
  5. this.sqlSessionFactory = this.buildSqlSessionFactory();
  6. }
  1. this.buildSqlSessionFactory();这个就是核心重点!!!
  1. protected SqlSessionFactory buildSqlSessionFactory() throws IOException {
  2. XMLConfigBuilder xmlConfigBuilder = null;
  3. Configuration targetConfiguration;
  4. if (this.configuration != null) {
  5. targetConfiguration = this.configuration;
  6. if (targetConfiguration.getVariables() == null) {
  7. targetConfiguration.setVariables(this.configurationProperties);
  8. } else if (this.configurationProperties != null) {
  9. targetConfiguration.getVariables().putAll(this.configurationProperties);
  10. }
  11. } else if (this.configLocation != null) {
  12. xmlConfigBuilder = new XMLConfigBuilder(this.configLocation.getInputStream(), (String)null, this.configurationProperties);
  13. targetConfiguration = xmlConfigBuilder.getConfiguration();
  14. } else {
  15. LOGGER.debug(() -> {
  16. return "Property 'configuration' or 'configLocation' not specified, using default MyBatis Configuration";
  17. });
  18. targetConfiguration = new Configuration();
  19. Optional.ofNullable(this.configurationProperties).ifPresent(targetConfiguration::setVariables);
  20. }
  21.  
  22. Optional.ofNullable(this.objectFactory).ifPresent(targetConfiguration::setObjectFactory);
  23. Optional.ofNullable(this.objectWrapperFactory).ifPresent(targetConfiguration::setObjectWrapperFactory);
  24. Optional.ofNullable(this.vfs).ifPresent(targetConfiguration::setVfsImpl);
  25. String[] typeHandlersPackageArray;
  26. if (StringUtils.hasLength(this.typeAliasesPackage)) {
  27. typeHandlersPackageArray = StringUtils.tokenizeToStringArray(this.typeAliasesPackage, ",; \t\n");
  28. Stream.of(typeHandlersPackageArray).forEach((packageToScan) -> {
  29. targetConfiguration.getTypeAliasRegistry().registerAliases(packageToScan, this.typeAliasesSuperType == null ? Object.class : this.typeAliasesSuperType);
  30. LOGGER.debug(() -> {
  31. return "Scanned package: '" + packageToScan + "' for aliases";
  32. });
  33. });
  34. }
  35.  
  36. if (!ObjectUtils.isEmpty(this.typeAliases)) {
  37. Stream.of(this.typeAliases).forEach((typeAlias) -> {
  38. targetConfiguration.getTypeAliasRegistry().registerAlias(typeAlias);
  39. LOGGER.debug(() -> {
  40. return "Registered type alias: '" + typeAlias + "'";
  41. });
  42. });
  43. }
  44.  
  45. if (!ObjectUtils.isEmpty(this.plugins)) {
  46. Stream.of(this.plugins).forEach((plugin) -> {
  47. targetConfiguration.addInterceptor(plugin);
  48. LOGGER.debug(() -> {
  49. return "Registered plugin: '" + plugin + "'";
  50. });
  51. });
  52. }
  53.  
  54. if (StringUtils.hasLength(this.typeHandlersPackage)) {
  55. typeHandlersPackageArray = StringUtils.tokenizeToStringArray(this.typeHandlersPackage, ",; \t\n");
  56. Stream.of(typeHandlersPackageArray).forEach((packageToScan) -> {
  57. targetConfiguration.getTypeHandlerRegistry().register(packageToScan);
  58. LOGGER.debug(() -> {
  59. return "Scanned package: '" + packageToScan + "' for type handlers";
  60. });
  61. });
  62. }
  63.  
  64. if (!ObjectUtils.isEmpty(this.typeHandlers)) {
  65. Stream.of(this.typeHandlers).forEach((typeHandler) -> {
  66. targetConfiguration.getTypeHandlerRegistry().register(typeHandler);
  67. LOGGER.debug(() -> {
  68. return "Registered type handler: '" + typeHandler + "'";
  69. });
  70. });
  71. }
  72.  
  73. if (this.databaseIdProvider != null) {
  74. try {
  75. targetConfiguration.setDatabaseId(this.databaseIdProvider.getDatabaseId(this.dataSource));
  76. } catch (SQLException var23) {
  77. throw new NestedIOException("Failed getting a databaseId", var23);
  78. }
  79. }
  80.  
  81. Optional.ofNullable(this.cache).ifPresent(targetConfiguration::addCache);
  82. if (xmlConfigBuilder != null) {
  83. try {
  84. xmlConfigBuilder.parse();
  85. LOGGER.debug(() -> {
  86. return "Parsed configuration file: '" + this.configLocation + "'";
  87. });
  88. } catch (Exception var21) {
  89. throw new NestedIOException("Failed to parse config resource: " + this.configLocation, var21);
  90. } finally {
  91. ErrorContext.instance().reset();
  92. }
  93. }
  94.  
  95. targetConfiguration.setEnvironment(new Environment(this.environment, (TransactionFactory)(this.transactionFactory == null ? new SpringManagedTransactionFactory() : this.transactionFactory), this.dataSource));
  96. if (!ObjectUtils.isEmpty(this.mapperLocations)) {
  97. Resource[] var24 = this.mapperLocations;
  98. int var4 = var24.length;
  99.  
  100. for(int var5 = 0; var5 < var4; ++var5) {
  101. Resource mapperLocation = var24[var5];
  102. if (mapperLocation != null) {
  103. try {
  104. XMLMapperBuilder xmlMapperBuilder = new XMLMapperBuilder(mapperLocation.getInputStream(), targetConfiguration, mapperLocation.toString(), targetConfiguration.getSqlFragments());
  105. xmlMapperBuilder.parse();
  106. } catch (Exception var19) {
  107. throw new NestedIOException("Failed to parse mapping resource: '" + mapperLocation + "'", var19);
  108. } finally {
  109. ErrorContext.instance().reset();
  110. }
  111.  
  112. LOGGER.debug(() -> {
  113. return "Parsed mapper file: '" + mapperLocation + "'";
  114. });
  115. }
  116. }
  117. } else {
  118. LOGGER.debug(() -> {
  119. return "Property 'mapperLocations' was not specified or no matching resources found";
  120. });
  121. }
  122.  
  123. return this.sqlSessionFactoryBuilder.build(targetConfiguration);
  124. }

这个方法我们慢慢仔细看:

  1. XMLConfigBuilder xmlConfigBuilder = null;
  2. Configuration targetConfiguration;
  3. if (this.configuration != null) {
  4. targetConfiguration = this.configuration;
  5. if (targetConfiguration.getVariables() == null) {
  6. targetConfiguration.setVariables(this.configurationProperties);
  7. } else if (this.configurationProperties != null) {
  8. targetConfiguration.getVariables().putAll(this.configurationProperties);
  9. }
  10. } else if (this.configLocation != null) {
  11. xmlConfigBuilder = new XMLConfigBuilder(this.configLocation.getInputStream(), (String)null, this.configurationProperties);
  12. targetConfiguration = xmlConfigBuilder.getConfiguration();
  13. } else {
  14. LOGGER.debug(() -> {
  15. return "Property 'configuration' or 'configLocation' not specified, using default MyBatis Configuration";
  16. });
  17. targetConfiguration = new Configuration();
  18. Optional.ofNullable(this.configurationProperties).ifPresent(targetConfiguration::setVariables);
  19. }

上面中标红的就是核心代码,

  1. public XMLConfigBuilder(InputStream inputStream, String environment, Properties props) {
  2. this(new XPathParser(inputStream, true, props, new XMLMapperEntityResolver()), environment, props);
  3. }
  1. public XPathParser(InputStream inputStream, boolean validation, Properties variables, EntityResolver entityResolver) {
  2. commonConstructor(validation, variables, entityResolver);
  3. this.document = createDocument(new InputSource(inputStream));
  4. }
  1. private Document createDocument(InputSource inputSource) {
  2. // important: this must only be called AFTER common constructor
  3. try {
  4. DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
  5. factory.setValidating(validation);
  6.  
  7. factory.setNamespaceAware(false);
  8. factory.setIgnoringComments(true);
  9. factory.setIgnoringElementContentWhitespace(false);
  10. factory.setCoalescing(false);
  11. factory.setExpandEntityReferences(true);
  12.  
  13. DocumentBuilder builder = factory.newDocumentBuilder();
  14. builder.setEntityResolver(entityResolver);
  15. builder.setErrorHandler(new ErrorHandler() {
  16. @Override
  17. public void error(SAXParseException exception) throws SAXException {
  18. throw exception;
  19. }
  20.  
  21. @Override
  22. public void fatalError(SAXParseException exception) throws SAXException {
  23. throw exception;
  24. }
  25.  
  26. @Override
  27. public void warning(SAXParseException exception) throws SAXException {
  28. }
  29. });
  30. return builder.parse(inputSource);
  31. } catch (Exception e) {
  32. throw new BuilderException("Error creating document instance. Cause: " + e, e);
  33. }
  34. }
  1. public Document parse(InputSource is) throws SAXException, IOException {
  2. if (is == null) {
  3. throw new IllegalArgumentException(
  4. DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN,
  5. "jaxp-null-input-source", null));
  6. }
  7. if (fSchemaValidator != null) {
  8. if (fSchemaValidationManager != null) {
  9. fSchemaValidationManager.reset();
  10. fUnparsedEntityHandler.reset();
  11. }
  12. resetSchemaValidator();
  13. }
  14. domParser.parse(is);
  15. Document doc = domParser.getDocument();
  16. domParser.dropDocumentReferences();
  17. return doc;
  18. }
  1. configLocation就算解析完成了;其他的
  1. typeAliasesPackageplugins都没什么好看的,不过
  1. plugins中通过添加interceptor完成插件的拦截入口,常用的就是PageHelper分页插件,后面可以具体看看这个是如何生效的!!
  1. if (!ObjectUtils.isEmpty(this.plugins)) {
  2. Stream.of(this.plugins).forEach((plugin) -> {
  3. targetConfiguration.addInterceptor(plugin);
  4. LOGGER.debug(() -> {
  5. return "Registered plugin: '" + plugin + "'";
  6. });
  7. });
  8. }

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

  1. protected final MapperRegistry mapperRegistry = new MapperRegistry(this);
  1. public class Configuration {
  2.  
  3. protected Environment environment;
  4.  
  5. protected boolean safeRowBoundsEnabled = false;
  6. protected boolean safeResultHandlerEnabled = true;
  7. protected boolean mapUnderscoreToCamelCase = false;
  8. protected boolean aggressiveLazyLoading = true;
  9. protected boolean multipleResultSetsEnabled = true;
  10. protected boolean useGeneratedKeys = false;
  11. protected boolean useColumnLabel = true;
  12. protected boolean cacheEnabled = true;
  13. protected boolean callSettersOnNulls = false;
  14. protected boolean useActualParamName = true;
  15.  
  16. protected String logPrefix;
  17. protected Class <? extends Log> logImpl;
  18. protected Class <? extends VFS> vfsImpl;
  19. protected LocalCacheScope localCacheScope = LocalCacheScope.SESSION;
  20. protected JdbcType jdbcTypeForNull = JdbcType.OTHER;
  21. protected Set<String> lazyLoadTriggerMethods = new HashSet<String>(Arrays.asList(new String[] { "equals", "clone", "hashCode", "toString" }));
  22. protected Integer defaultStatementTimeout;
  23. protected Integer defaultFetchSize;
  24. protected ExecutorType defaultExecutorType = ExecutorType.SIMPLE;
  25. protected AutoMappingBehavior autoMappingBehavior = AutoMappingBehavior.PARTIAL;
  26. protected AutoMappingUnknownColumnBehavior autoMappingUnknownColumnBehavior = AutoMappingUnknownColumnBehavior.NONE;
  27.  
  28. protected Properties variables = new Properties();
  29. protected ReflectorFactory reflectorFactory = new DefaultReflectorFactory();
  30. protected ObjectFactory objectFactory = new DefaultObjectFactory();
  31. protected ObjectWrapperFactory objectWrapperFactory = new DefaultObjectWrapperFactory();
  32.  
  33. protected boolean lazyLoadingEnabled = false;
  34. protected ProxyFactory proxyFactory = new JavassistProxyFactory(); // #224 Using internal Javassist instead of OGNL
  35.  
  36. protected String databaseId;
  37. /**
  38. * Configuration factory class.
  39. * Used to create Configuration for loading deserialized unread properties.
  40. *
  41. * @see <a href='https://code.google.com/p/mybatis/issues/detail?id=300'>Issue 300 (google code)</a>
  42. */
  43. protected Class<?> configurationFactory;
  44.  
  45. protected final MapperRegistry mapperRegistry = new MapperRegistry(this);
  46. protected final InterceptorChain interceptorChain = new InterceptorChain();
  47. protected final TypeHandlerRegistry typeHandlerRegistry = new TypeHandlerRegistry();
  48. protected final TypeAliasRegistry typeAliasRegistry = new TypeAliasRegistry();
  49. protected final LanguageDriverRegistry languageRegistry = new LanguageDriverRegistry();
  50.  
  51. protected final Map<String, MappedStatement> mappedStatements = new StrictMap<MappedStatement>("Mapped Statements collection");
  52. protected final Map<String, Cache> caches = new StrictMap<Cache>("Caches collection");
  53. protected final Map<String, ResultMap> resultMaps = new StrictMap<ResultMap>("Result Maps collection");
  54. protected final Map<String, ParameterMap> parameterMaps = new StrictMap<ParameterMap>("Parameter Maps collection");
  55. protected final Map<String, KeyGenerator> keyGenerators = new StrictMap<KeyGenerator>("Key Generators collection");
  56.  
  57. protected final Set<String> loadedResources = new HashSet<String>();
  58. protected final Map<String, XNode> sqlFragments = new StrictMap<XNode>("XML fragments parsed from previous mappers");
  59.  
  60. protected final Collection<XMLStatementBuilder> incompleteStatements = new LinkedList<XMLStatementBuilder>();
  61. protected final Collection<CacheRefResolver> incompleteCacheRefs = new LinkedList<CacheRefResolver>();
  62. protected final Collection<ResultMapResolver> incompleteResultMaps = new LinkedList<ResultMapResolver>();
  63. protected final Collection<MethodResolver> incompleteMethods = new LinkedList<MethodResolver>();
  64.  
  65. /*
  66. * A map holds cache-ref relationship. The key is the namespace that
  67. * references a cache bound to another namespace and the value is the
  68. * namespace which the actual cache is bound to.
  69. */
  70. protected final Map<String, String> cacheRefMap = new HashMap<String, String>();
  71.  
  72. public Configuration(Environment environment) {
  73. this();
  74. this.environment = environment;
  75. }
  76.  
  77. public Configuration() {
  78. typeAliasRegistry.registerAlias("JDBC", JdbcTransactionFactory.class);
  79. typeAliasRegistry.registerAlias("MANAGED", ManagedTransactionFactory.class);
  80.  
  81. typeAliasRegistry.registerAlias("JNDI", JndiDataSourceFactory.class);
  82. typeAliasRegistry.registerAlias("POOLED", PooledDataSourceFactory.class);
  83. typeAliasRegistry.registerAlias("UNPOOLED", UnpooledDataSourceFactory.class);
  84.  
  85. typeAliasRegistry.registerAlias("PERPETUAL", PerpetualCache.class);
  86. typeAliasRegistry.registerAlias("FIFO", FifoCache.class);
  87. typeAliasRegistry.registerAlias("LRU", LruCache.class);
  88. typeAliasRegistry.registerAlias("SOFT", SoftCache.class);
  89. typeAliasRegistry.registerAlias("WEAK", WeakCache.class);
  90.  
  91. typeAliasRegistry.registerAlias("DB_VENDOR", VendorDatabaseIdProvider.class);
  92.  
  93. typeAliasRegistry.registerAlias("XML", XMLLanguageDriver.class);
  94. typeAliasRegistry.registerAlias("RAW", RawLanguageDriver.class);
  95.  
  96. typeAliasRegistry.registerAlias("SLF4J", Slf4jImpl.class);
  97. typeAliasRegistry.registerAlias("COMMONS_LOGGING", JakartaCommonsLoggingImpl.class);
  98. typeAliasRegistry.registerAlias("LOG4J", Log4jImpl.class);
  99. typeAliasRegistry.registerAlias("LOG4J2", Log4j2Impl.class);
  100. typeAliasRegistry.registerAlias("JDK_LOGGING", Jdk14LoggingImpl.class);
  101. typeAliasRegistry.registerAlias("STDOUT_LOGGING", StdOutImpl.class);
  102. typeAliasRegistry.registerAlias("NO_LOGGING", NoLoggingImpl.class);
  103.  
  104. typeAliasRegistry.registerAlias("CGLIB", CglibProxyFactory.class);
  105. typeAliasRegistry.registerAlias("JAVASSIST", JavassistProxyFactory.class);
  106.  
  107. languageRegistry.setDefaultDriverClass(XMLLanguageDriver.class);
  108. languageRegistry.register(RawLanguageDriver.class);
  109. }
  1.  

MyBatis源码解析(一)的更多相关文章

  1. 【MyBatis源码解析】MyBatis一二级缓存

    MyBatis缓存 我们知道,频繁的数据库操作是非常耗费性能的(主要是因为对于DB而言,数据是持久化在磁盘中的,因此查询操作需要通过IO,IO操作速度相比内存操作速度慢了好几个量级),尤其是对于一些相 ...

  2. Mybatis源码解析-DynamicSqlSource和RawSqlSource的区别

    XMLLanguageDriver是ibatis的默认解析sql节点帮助类,其中的方法其会调用生成DynamicSqlSource和RawSqlSource这两个帮助类,本文将对此作下简单的简析 应用 ...

  3. mybatis源码-解析配置文件(四-1)之配置文件Mapper解析(cache)

    目录 1. 简介 2. 解析 3 StrictMap 3.1 区别HashMap:键必须为String 3.2 区别HashMap:多了成员变量 name 3.3 区别HashMap:key 的处理多 ...

  4. mybatis源码-解析配置文件(四)之配置文件Mapper解析

    在 mybatis源码-解析配置文件(三)之配置文件Configuration解析 中, 讲解了 Configuration 是如何解析的. 其中, mappers作为configuration节点的 ...

  5. mybatis源码-解析配置文件(三)之配置文件Configuration解析

    目录 1. 简介 1.1 系列内容 1.2 适合对象 1.3 本文内容 2. 配置文件 2.1 mysql.properties 2.2 mybatis-config.xml 3. Configura ...

  6. Mybatis源码解析,一步一步从浅入深(一):创建准备工程

    Spring SpringMVC Mybatis(简称ssm)是一个很流行的java web框架,而Mybatis作为ORM 持久层框架,因其灵活简单,深受青睐.而且现在的招聘职位中都要求应试者熟悉M ...

  7. Mybatis源码解析,一步一步从浅入深(二):按步骤解析源码

    在文章:Mybatis源码解析,一步一步从浅入深(一):创建准备工程,中我们为了解析mybatis源码创建了一个mybatis的简单工程(源码已上传github,链接在文章末尾),并实现了一个查询功能 ...

  8. Mybatis源码解析,一步一步从浅入深(三):实例化xml配置解析器(XMLConfigBuilder)

    在上一篇文章:Mybatis源码解析,一步一步从浅入深(二):按步骤解析源码 ,中我们看到 代码:XMLConfigBuilder parser = new XMLConfigBuilder(read ...

  9. Mybatis源码解析,一步一步从浅入深(四):将configuration.xml的解析到Configuration对象实例

    在Mybatis源码解析,一步一步从浅入深(二):按步骤解析源码中我们看到了XMLConfigBuilder(xml配置解析器)的实例化.而且这个实例化过程在文章:Mybatis源码解析,一步一步从浅 ...

  10. Mybatis源码解析,一步一步从浅入深(五):mapper节点的解析

    在上一篇文章Mybatis源码解析,一步一步从浅入深(四):将configuration.xml的解析到Configuration对象实例中我们谈到了properties,settings,envir ...

随机推荐

  1. 使用Windows API发送HTTP请求

    先看一个简单的GET示例 #include <Windows.h> #include <winhttp.h> #include <stdio.h> int main ...

  2. Delphi里可将纯虚类实例化,还可调用非虚函数

    这是与Java/C++的巨大不同.目前还没仔细想这个特征与TClass之间的联系,先记住结论再说.以后再回来修改这个帖子. unit Unit1; interface uses Windows, Me ...

  3. BAT网络运维常见面试题目总结

    BAT常见面试题目总结 Author:Danbo 2015-7-11 TCP/IP详解鸟哥Linux的书网络安全ping的原理make的过程文件有哪些类型各种Linux发行版的区别.有关suid的作用 ...

  4. SPOJ7258

    传送门 这题可以参考平衡树求第k大的过程,需要预处理一下从当前节点往下走能走出多少个子串. 原本准备存个图用反向的topsort,发现极为麻烦,看了别人的代码后发现,他们按step大小用了基排,省了很 ...

  5. SPOJ1811 LCS SAM

    后缀自动机简单题. 其主要思路是,先对第一个字符串建立后缀自动机,把第二个串放在上面匹配, 若当前状态s有字符x的转移,直接转移len=step+1. 若当前状态s没有向字符x的转移,退回pres检查 ...

  6. html5--5-3 给直线添加样式

    html5--5-3 给直线添加样式 学习要点 strokeStyle属性:设置颜色.渐变或模式(本节课只涉及到颜色) lineWidth属性:--设置线宽 Canvas的路径方法 moveTo() ...

  7. php filter 安全过滤函数

    转自:http://www.blags.org/archives/741.html php 利用filter 扩展编写的参数处理静态类,欢迎使用.希望大家看得开心,用得放心. <?php /** ...

  8. hdu-5773 The All-purpose Zero(LIS)

    题目链接: The All-purpose Zero Time Limit: 2000/1000 MS (Java/Others)     Memory Limit: 65536/65536 K (J ...

  9. codeforces 701C C. They Are Everywhere(尺取法)

    题目链接: C. They Are Everywhere time limit per test 2 seconds   memory limit per test 256 megabytes inp ...

  10. Python: PS 滤镜--素描

    本文用 Python 实现 PS 滤镜中的素描特效,具体的算法原理和效果可以参考之前的博客: http://blog.csdn.net/matrix_space/article/details/386 ...