MyBatis源码解析(一)
- <!-- mybatis文件配置,扫描所有mapper文件 -->
<!--SqlSessionFactoryBean的初始化参数-->
- <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
- <property name="dataSource" ref="dataSource"/>
- <property name="configLocation" value="classpath:/spring/mybatis.xml"/>
- <property name="typeAliasesPackage" value="com.cloudwalk.shark.model"/>
- <property name="mapperLocations" value="classpath*:mapper/*.xml"/>
- <property name="plugins">
- <array>
- <bean class="com.github.pagehelper.PageHelper">
- <property name="properties">
- <!--使用下面的方式配置参数,一行配置一个 -->
- <value>
- dialect=mysql
- </value>
- </property>
- </bean>
- </array>
- </property>
- </bean>
- <!-- spring与mybatis整合配置,扫描所有dao,指定的映射器类是接口,接口方法可以用注解来指定 SQL 语句,但是 MyBatis 的映射器 XML 文件也可以用。 -->
- <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"
- p:basePackage="com.cloudwalk.shark.mapper"
- p:sqlSessionFactoryBeanName="sqlSessionFactory"/>
下面跟踪SqlSessionFactoryBean.java的源码
- public class SqlSessionFactoryBean implements FactoryBean<SqlSessionFactory>, InitializingBean, ApplicationListener<ApplicationEvent> {
- }
实现了InitializingBean,ApplicationListener,自然而然就会在Spring加载的过程中做一些操作:
- public void afterPropertiesSet() throws Exception {
- Assert.notNull(this.dataSource, "Property 'dataSource' is required");
- Assert.notNull(this.sqlSessionFactoryBuilder, "Property 'sqlSessionFactoryBuilder' is required");
- Assert.state(this.configuration == null && this.configLocation == null || this.configuration == null || this.configLocation == null, "Property 'configuration' and 'configLocation' can not specified with together");
- this.sqlSessionFactory = this.buildSqlSessionFactory();
- }
- this.buildSqlSessionFactory();这个就是核心重点!!!
- protected SqlSessionFactory buildSqlSessionFactory() throws IOException {
- XMLConfigBuilder xmlConfigBuilder = null;
- Configuration targetConfiguration;
- if (this.configuration != null) {
- targetConfiguration = this.configuration;
- if (targetConfiguration.getVariables() == null) {
- targetConfiguration.setVariables(this.configurationProperties);
- } else if (this.configurationProperties != null) {
- targetConfiguration.getVariables().putAll(this.configurationProperties);
- }
- } else if (this.configLocation != null) {
- xmlConfigBuilder = new XMLConfigBuilder(this.configLocation.getInputStream(), (String)null, this.configurationProperties);
- targetConfiguration = xmlConfigBuilder.getConfiguration();
- } else {
- LOGGER.debug(() -> {
- return "Property 'configuration' or 'configLocation' not specified, using default MyBatis Configuration";
- });
- targetConfiguration = new Configuration();
- Optional.ofNullable(this.configurationProperties).ifPresent(targetConfiguration::setVariables);
- }
- Optional.ofNullable(this.objectFactory).ifPresent(targetConfiguration::setObjectFactory);
- Optional.ofNullable(this.objectWrapperFactory).ifPresent(targetConfiguration::setObjectWrapperFactory);
- Optional.ofNullable(this.vfs).ifPresent(targetConfiguration::setVfsImpl);
- String[] typeHandlersPackageArray;
- if (StringUtils.hasLength(this.typeAliasesPackage)) {
- typeHandlersPackageArray = StringUtils.tokenizeToStringArray(this.typeAliasesPackage, ",; \t\n");
- Stream.of(typeHandlersPackageArray).forEach((packageToScan) -> {
- targetConfiguration.getTypeAliasRegistry().registerAliases(packageToScan, this.typeAliasesSuperType == null ? Object.class : this.typeAliasesSuperType);
- LOGGER.debug(() -> {
- return "Scanned package: '" + packageToScan + "' for aliases";
- });
- });
- }
- if (!ObjectUtils.isEmpty(this.typeAliases)) {
- Stream.of(this.typeAliases).forEach((typeAlias) -> {
- targetConfiguration.getTypeAliasRegistry().registerAlias(typeAlias);
- LOGGER.debug(() -> {
- return "Registered type alias: '" + typeAlias + "'";
- });
- });
- }
- if (!ObjectUtils.isEmpty(this.plugins)) {
- Stream.of(this.plugins).forEach((plugin) -> {
- targetConfiguration.addInterceptor(plugin);
- LOGGER.debug(() -> {
- return "Registered plugin: '" + plugin + "'";
- });
- });
- }
- if (StringUtils.hasLength(this.typeHandlersPackage)) {
- typeHandlersPackageArray = StringUtils.tokenizeToStringArray(this.typeHandlersPackage, ",; \t\n");
- Stream.of(typeHandlersPackageArray).forEach((packageToScan) -> {
- targetConfiguration.getTypeHandlerRegistry().register(packageToScan);
- LOGGER.debug(() -> {
- return "Scanned package: '" + packageToScan + "' for type handlers";
- });
- });
- }
- if (!ObjectUtils.isEmpty(this.typeHandlers)) {
- Stream.of(this.typeHandlers).forEach((typeHandler) -> {
- targetConfiguration.getTypeHandlerRegistry().register(typeHandler);
- LOGGER.debug(() -> {
- return "Registered type handler: '" + typeHandler + "'";
- });
- });
- }
- if (this.databaseIdProvider != null) {
- try {
- targetConfiguration.setDatabaseId(this.databaseIdProvider.getDatabaseId(this.dataSource));
- } catch (SQLException var23) {
- throw new NestedIOException("Failed getting a databaseId", var23);
- }
- }
- Optional.ofNullable(this.cache).ifPresent(targetConfiguration::addCache);
- if (xmlConfigBuilder != null) {
- try {
- xmlConfigBuilder.parse();
- LOGGER.debug(() -> {
- return "Parsed configuration file: '" + this.configLocation + "'";
- });
- } catch (Exception var21) {
- throw new NestedIOException("Failed to parse config resource: " + this.configLocation, var21);
- } finally {
- ErrorContext.instance().reset();
- }
- }
- targetConfiguration.setEnvironment(new Environment(this.environment, (TransactionFactory)(this.transactionFactory == null ? new SpringManagedTransactionFactory() : this.transactionFactory), this.dataSource));
- if (!ObjectUtils.isEmpty(this.mapperLocations)) {
- Resource[] var24 = this.mapperLocations;
- int var4 = var24.length;
- for(int var5 = 0; var5 < var4; ++var5) {
- Resource mapperLocation = var24[var5];
- if (mapperLocation != null) {
- try {
- XMLMapperBuilder xmlMapperBuilder = new XMLMapperBuilder(mapperLocation.getInputStream(), targetConfiguration, mapperLocation.toString(), targetConfiguration.getSqlFragments());
- xmlMapperBuilder.parse();
- } catch (Exception var19) {
- throw new NestedIOException("Failed to parse mapping resource: '" + mapperLocation + "'", var19);
- } finally {
- ErrorContext.instance().reset();
- }
- LOGGER.debug(() -> {
- return "Parsed mapper file: '" + mapperLocation + "'";
- });
- }
- }
- } else {
- LOGGER.debug(() -> {
- return "Property 'mapperLocations' was not specified or no matching resources found";
- });
- }
- return this.sqlSessionFactoryBuilder.build(targetConfiguration);
- }
这个方法我们慢慢仔细看:
- XMLConfigBuilder xmlConfigBuilder = null;
- Configuration targetConfiguration;
- if (this.configuration != null) {
- targetConfiguration = this.configuration;
- if (targetConfiguration.getVariables() == null) {
- targetConfiguration.setVariables(this.configurationProperties);
- } else if (this.configurationProperties != null) {
- targetConfiguration.getVariables().putAll(this.configurationProperties);
- }
- } else if (this.configLocation != null) {
- xmlConfigBuilder = new XMLConfigBuilder(this.configLocation.getInputStream(), (String)null, this.configurationProperties);
- targetConfiguration = xmlConfigBuilder.getConfiguration();
- } else {
- LOGGER.debug(() -> {
- return "Property 'configuration' or 'configLocation' not specified, using default MyBatis Configuration";
- });
- targetConfiguration = new Configuration();
- Optional.ofNullable(this.configurationProperties).ifPresent(targetConfiguration::setVariables);
- }
上面中标红的就是核心代码,
- public XMLConfigBuilder(InputStream inputStream, String environment, Properties props) {
- this(new XPathParser(inputStream, true, props, new XMLMapperEntityResolver()), environment, props);
- }
- public XPathParser(InputStream inputStream, boolean validation, Properties variables, EntityResolver entityResolver) {
- commonConstructor(validation, variables, entityResolver);
- this.document = createDocument(new InputSource(inputStream));
- }
- private Document createDocument(InputSource inputSource) {
- // important: this must only be called AFTER common constructor
- try {
- DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
- factory.setValidating(validation);
- factory.setNamespaceAware(false);
- factory.setIgnoringComments(true);
- factory.setIgnoringElementContentWhitespace(false);
- factory.setCoalescing(false);
- factory.setExpandEntityReferences(true);
- DocumentBuilder builder = factory.newDocumentBuilder();
- builder.setEntityResolver(entityResolver);
- builder.setErrorHandler(new ErrorHandler() {
- @Override
- public void error(SAXParseException exception) throws SAXException {
- throw exception;
- }
- @Override
- public void fatalError(SAXParseException exception) throws SAXException {
- throw exception;
- }
- @Override
- public void warning(SAXParseException exception) throws SAXException {
- }
- });
- return builder.parse(inputSource);
- } catch (Exception e) {
- throw new BuilderException("Error creating document instance. Cause: " + e, e);
- }
- }
- public Document parse(InputSource is) throws SAXException, IOException {
- if (is == null) {
- throw new IllegalArgumentException(
- DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN,
- "jaxp-null-input-source", null));
- }
- if (fSchemaValidator != null) {
- if (fSchemaValidationManager != null) {
- fSchemaValidationManager.reset();
- fUnparsedEntityHandler.reset();
- }
- resetSchemaValidator();
- }
- domParser.parse(is);
- Document doc = domParser.getDocument();
- domParser.dropDocumentReferences();
- return doc;
- }
- configLocation就算解析完成了;其他的
- typeAliasesPackage,plugins都没什么好看的,不过
- plugins中通过添加interceptor完成插件的拦截入口,常用的就是PageHelper分页插件,后面可以具体看看这个是如何生效的!!
- if (!ObjectUtils.isEmpty(this.plugins)) {
- Stream.of(this.plugins).forEach((plugin) -> {
- targetConfiguration.addInterceptor(plugin);
- LOGGER.debug(() -> {
- return "Registered plugin: '" + plugin + "'";
- });
- });
- }
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
- protected final MapperRegistry mapperRegistry = new MapperRegistry(this);
- public class Configuration {
- protected Environment environment;
- protected boolean safeRowBoundsEnabled = false;
- protected boolean safeResultHandlerEnabled = true;
- protected boolean mapUnderscoreToCamelCase = false;
- protected boolean aggressiveLazyLoading = true;
- protected boolean multipleResultSetsEnabled = true;
- protected boolean useGeneratedKeys = false;
- protected boolean useColumnLabel = true;
- protected boolean cacheEnabled = true;
- protected boolean callSettersOnNulls = false;
- protected boolean useActualParamName = true;
- protected String logPrefix;
- protected Class <? extends Log> logImpl;
- protected Class <? extends VFS> vfsImpl;
- protected LocalCacheScope localCacheScope = LocalCacheScope.SESSION;
- protected JdbcType jdbcTypeForNull = JdbcType.OTHER;
- protected Set<String> lazyLoadTriggerMethods = new HashSet<String>(Arrays.asList(new String[] { "equals", "clone", "hashCode", "toString" }));
- protected Integer defaultStatementTimeout;
- protected Integer defaultFetchSize;
- protected ExecutorType defaultExecutorType = ExecutorType.SIMPLE;
- protected AutoMappingBehavior autoMappingBehavior = AutoMappingBehavior.PARTIAL;
- protected AutoMappingUnknownColumnBehavior autoMappingUnknownColumnBehavior = AutoMappingUnknownColumnBehavior.NONE;
- protected Properties variables = new Properties();
- protected ReflectorFactory reflectorFactory = new DefaultReflectorFactory();
- protected ObjectFactory objectFactory = new DefaultObjectFactory();
- protected ObjectWrapperFactory objectWrapperFactory = new DefaultObjectWrapperFactory();
- protected boolean lazyLoadingEnabled = false;
- protected ProxyFactory proxyFactory = new JavassistProxyFactory(); // #224 Using internal Javassist instead of OGNL
- protected String databaseId;
- /**
- * Configuration factory class.
- * Used to create Configuration for loading deserialized unread properties.
- *
- * @see <a href='https://code.google.com/p/mybatis/issues/detail?id=300'>Issue 300 (google code)</a>
- */
- protected Class<?> configurationFactory;
- protected final MapperRegistry mapperRegistry = new MapperRegistry(this);
- protected final InterceptorChain interceptorChain = new InterceptorChain();
- protected final TypeHandlerRegistry typeHandlerRegistry = new TypeHandlerRegistry();
- protected final TypeAliasRegistry typeAliasRegistry = new TypeAliasRegistry();
- protected final LanguageDriverRegistry languageRegistry = new LanguageDriverRegistry();
- protected final Map<String, MappedStatement> mappedStatements = new StrictMap<MappedStatement>("Mapped Statements collection");
- protected final Map<String, Cache> caches = new StrictMap<Cache>("Caches collection");
- protected final Map<String, ResultMap> resultMaps = new StrictMap<ResultMap>("Result Maps collection");
- protected final Map<String, ParameterMap> parameterMaps = new StrictMap<ParameterMap>("Parameter Maps collection");
- protected final Map<String, KeyGenerator> keyGenerators = new StrictMap<KeyGenerator>("Key Generators collection");
- protected final Set<String> loadedResources = new HashSet<String>();
- protected final Map<String, XNode> sqlFragments = new StrictMap<XNode>("XML fragments parsed from previous mappers");
- protected final Collection<XMLStatementBuilder> incompleteStatements = new LinkedList<XMLStatementBuilder>();
- protected final Collection<CacheRefResolver> incompleteCacheRefs = new LinkedList<CacheRefResolver>();
- protected final Collection<ResultMapResolver> incompleteResultMaps = new LinkedList<ResultMapResolver>();
- protected final Collection<MethodResolver> incompleteMethods = new LinkedList<MethodResolver>();
- /*
- * A map holds cache-ref relationship. The key is the namespace that
- * references a cache bound to another namespace and the value is the
- * namespace which the actual cache is bound to.
- */
- protected final Map<String, String> cacheRefMap = new HashMap<String, String>();
- public Configuration(Environment environment) {
- this();
- this.environment = environment;
- }
- public Configuration() {
- typeAliasRegistry.registerAlias("JDBC", JdbcTransactionFactory.class);
- typeAliasRegistry.registerAlias("MANAGED", ManagedTransactionFactory.class);
- typeAliasRegistry.registerAlias("JNDI", JndiDataSourceFactory.class);
- typeAliasRegistry.registerAlias("POOLED", PooledDataSourceFactory.class);
- typeAliasRegistry.registerAlias("UNPOOLED", UnpooledDataSourceFactory.class);
- typeAliasRegistry.registerAlias("PERPETUAL", PerpetualCache.class);
- typeAliasRegistry.registerAlias("FIFO", FifoCache.class);
- typeAliasRegistry.registerAlias("LRU", LruCache.class);
- typeAliasRegistry.registerAlias("SOFT", SoftCache.class);
- typeAliasRegistry.registerAlias("WEAK", WeakCache.class);
- typeAliasRegistry.registerAlias("DB_VENDOR", VendorDatabaseIdProvider.class);
- typeAliasRegistry.registerAlias("XML", XMLLanguageDriver.class);
- typeAliasRegistry.registerAlias("RAW", RawLanguageDriver.class);
- typeAliasRegistry.registerAlias("SLF4J", Slf4jImpl.class);
- typeAliasRegistry.registerAlias("COMMONS_LOGGING", JakartaCommonsLoggingImpl.class);
- typeAliasRegistry.registerAlias("LOG4J", Log4jImpl.class);
- typeAliasRegistry.registerAlias("LOG4J2", Log4j2Impl.class);
- typeAliasRegistry.registerAlias("JDK_LOGGING", Jdk14LoggingImpl.class);
- typeAliasRegistry.registerAlias("STDOUT_LOGGING", StdOutImpl.class);
- typeAliasRegistry.registerAlias("NO_LOGGING", NoLoggingImpl.class);
- typeAliasRegistry.registerAlias("CGLIB", CglibProxyFactory.class);
- typeAliasRegistry.registerAlias("JAVASSIST", JavassistProxyFactory.class);
- languageRegistry.setDefaultDriverClass(XMLLanguageDriver.class);
- languageRegistry.register(RawLanguageDriver.class);
- }
MyBatis源码解析(一)的更多相关文章
- 【MyBatis源码解析】MyBatis一二级缓存
MyBatis缓存 我们知道,频繁的数据库操作是非常耗费性能的(主要是因为对于DB而言,数据是持久化在磁盘中的,因此查询操作需要通过IO,IO操作速度相比内存操作速度慢了好几个量级),尤其是对于一些相 ...
- Mybatis源码解析-DynamicSqlSource和RawSqlSource的区别
XMLLanguageDriver是ibatis的默认解析sql节点帮助类,其中的方法其会调用生成DynamicSqlSource和RawSqlSource这两个帮助类,本文将对此作下简单的简析 应用 ...
- mybatis源码-解析配置文件(四-1)之配置文件Mapper解析(cache)
目录 1. 简介 2. 解析 3 StrictMap 3.1 区别HashMap:键必须为String 3.2 区别HashMap:多了成员变量 name 3.3 区别HashMap:key 的处理多 ...
- mybatis源码-解析配置文件(四)之配置文件Mapper解析
在 mybatis源码-解析配置文件(三)之配置文件Configuration解析 中, 讲解了 Configuration 是如何解析的. 其中, mappers作为configuration节点的 ...
- mybatis源码-解析配置文件(三)之配置文件Configuration解析
目录 1. 简介 1.1 系列内容 1.2 适合对象 1.3 本文内容 2. 配置文件 2.1 mysql.properties 2.2 mybatis-config.xml 3. Configura ...
- Mybatis源码解析,一步一步从浅入深(一):创建准备工程
Spring SpringMVC Mybatis(简称ssm)是一个很流行的java web框架,而Mybatis作为ORM 持久层框架,因其灵活简单,深受青睐.而且现在的招聘职位中都要求应试者熟悉M ...
- Mybatis源码解析,一步一步从浅入深(二):按步骤解析源码
在文章:Mybatis源码解析,一步一步从浅入深(一):创建准备工程,中我们为了解析mybatis源码创建了一个mybatis的简单工程(源码已上传github,链接在文章末尾),并实现了一个查询功能 ...
- Mybatis源码解析,一步一步从浅入深(三):实例化xml配置解析器(XMLConfigBuilder)
在上一篇文章:Mybatis源码解析,一步一步从浅入深(二):按步骤解析源码 ,中我们看到 代码:XMLConfigBuilder parser = new XMLConfigBuilder(read ...
- Mybatis源码解析,一步一步从浅入深(四):将configuration.xml的解析到Configuration对象实例
在Mybatis源码解析,一步一步从浅入深(二):按步骤解析源码中我们看到了XMLConfigBuilder(xml配置解析器)的实例化.而且这个实例化过程在文章:Mybatis源码解析,一步一步从浅 ...
- Mybatis源码解析,一步一步从浅入深(五):mapper节点的解析
在上一篇文章Mybatis源码解析,一步一步从浅入深(四):将configuration.xml的解析到Configuration对象实例中我们谈到了properties,settings,envir ...
随机推荐
- 使用Windows API发送HTTP请求
先看一个简单的GET示例 #include <Windows.h> #include <winhttp.h> #include <stdio.h> int main ...
- Delphi里可将纯虚类实例化,还可调用非虚函数
这是与Java/C++的巨大不同.目前还没仔细想这个特征与TClass之间的联系,先记住结论再说.以后再回来修改这个帖子. unit Unit1; interface uses Windows, Me ...
- BAT网络运维常见面试题目总结
BAT常见面试题目总结 Author:Danbo 2015-7-11 TCP/IP详解鸟哥Linux的书网络安全ping的原理make的过程文件有哪些类型各种Linux发行版的区别.有关suid的作用 ...
- SPOJ7258
传送门 这题可以参考平衡树求第k大的过程,需要预处理一下从当前节点往下走能走出多少个子串. 原本准备存个图用反向的topsort,发现极为麻烦,看了别人的代码后发现,他们按step大小用了基排,省了很 ...
- SPOJ1811 LCS SAM
后缀自动机简单题. 其主要思路是,先对第一个字符串建立后缀自动机,把第二个串放在上面匹配, 若当前状态s有字符x的转移,直接转移len=step+1. 若当前状态s没有向字符x的转移,退回pres检查 ...
- html5--5-3 给直线添加样式
html5--5-3 给直线添加样式 学习要点 strokeStyle属性:设置颜色.渐变或模式(本节课只涉及到颜色) lineWidth属性:--设置线宽 Canvas的路径方法 moveTo() ...
- php filter 安全过滤函数
转自:http://www.blags.org/archives/741.html php 利用filter 扩展编写的参数处理静态类,欢迎使用.希望大家看得开心,用得放心. <?php /** ...
- hdu-5773 The All-purpose Zero(LIS)
题目链接: The All-purpose Zero Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (J ...
- codeforces 701C C. They Are Everywhere(尺取法)
题目链接: C. They Are Everywhere time limit per test 2 seconds memory limit per test 256 megabytes inp ...
- Python: PS 滤镜--素描
本文用 Python 实现 PS 滤镜中的素描特效,具体的算法原理和效果可以参考之前的博客: http://blog.csdn.net/matrix_space/article/details/386 ...