mybatis 的配置文件解析又XMLConfigBuilder的parseConfiguration方法来完成,解析结果都存在Configuration这个类中
private void parseConfiguration(XNode root) {//根节点 try { //解析别名 typeAliasesElement(root.evalNode("typeAliases")); //解析插件 pluginElement(root.evalNode("plugins")); //对象工厂解析 //MyBatis 每次创建结果对象的新实例时,它都会使用一个对象工厂(ObjectFactory)实例来完成 objectFactoryElement(root.evalNode("objectFactory")); // objectWrapperFactoryElement(root.evalNode("objectWrapperFactory")); //解析属性 propertiesElement(root.evalNode("properties")); //解析mybatis参数 settingsElement(root.evalNode("settings")); //解析环境 environmentsElement(root.evalNode("environments")); //解析类型处理 typeHandlerElement(root.evalNode("typeHandlers")); //解析mapper映射文件 mapperElement(root.evalNode("mappers")); } catch (Exception e) { throw new BuilderException("Error parsing SQL Mapper Configuration. Cause: " + e, e); } }
别名解析
private void typeAliasesElement(XNode parent) { if (parent != null) { for (XNode child : parent.getChildren()) { String alias = child.getStringAttribute("alias"); String type = child.getStringAttribute("type"); try { Class<?> clazz = Resources.classForName(type); if (alias == null) { //没有设别名时 typeAliasRegistry.registerAlias(clazz); } else { //有设别名 typeAliasRegistry.registerAlias(alias, clazz); } } catch (ClassNotFoundException e) { throw new BuilderException("Error registering typeAlias for '" + alias + "'. Cause: " + e, e); } } } } public void registerAlias(Class type) { String alias = type.getSimpleName(); //从注解上获取 Alias aliasAnnotation = (Alias) type.getAnnotation(Alias.class); if (aliasAnnotation != null) { alias = aliasAnnotation.value(); } registerAlias(alias, type); } public void registerAlias(String alias, Class value) { assert alias != null; String key = alias.toLowerCase(); if (TYPE_ALIASES.containsKey(key) && !TYPE_ALIASES.get(key).equals(value.getName()) && TYPE_ALIASES.get(alias) != null) { if (!value.equals(TYPE_ALIASES.get(alias))) { throw new TypeException("The alias '" + alias + "' is already mapped to the value '" + TYPE_ALIASES.get(alias).getName() + "'."); } } //存入hashMaplim TYPE_ALIASES.put(key, value); }
插件解析
private void pluginElement(XNode parent) throws Exception { if (parent != null) { for (XNode child : parent.getChildren()) { String interceptor = child.getStringAttribute("interceptor"); //获取插件属性 Properties properties = child.getChildrenAsProperties(); Interceptor interceptorInstance = (Interceptor) resolveClass(interceptor).newInstance(); interceptorInstance.setProperties(properties); //加入到configuration类的插件执行链里面,其实就是List configuration.addInterceptor(interceptorInstance); } }
z工厂对象解析
private void objectFactoryElement(XNode context) throws Exception { if (context != null) { String type = context.getStringAttribute("type"); Properties properties = context.getChildrenAsProperties(); ObjectFactory factory = (ObjectFactory) resolveClass(type).newInstance(); factory.setProperties(properties); //替换默认的DefaultObjectFactory工厂 configuration.setObjectFactory(factory); } }
解析属性
private void propertiesElement(XNode context) throws Exception { if (context != null) { Properties defaults = context.getChildrenAsProperties(); String resource = context.getStringAttribute("resource"); String url = context.getStringAttribute("url"); if (resource != null && url != null) { throw new BuilderException("The properties element cannot specify both a URL and a resource based property file reference. Please specify one or the other."); } if (resource != null) { defaults.putAll(Resources.getResourceAsProperties(resource)); } else if (url != null) { defaults.putAll(Resources.getUrlAsProperties(url)); } Properties vars = configuration.getVariables(); if (vars != null) { defaults.putAll(vars); } parser.setVariables(defaults); configuration.setVariables(defaults); } }
解析mybatis参数
private void settingsElement(XNode context) throws Exception { if (context != null) { Properties props = context.getChildrenAsProperties(); // Check that all settings are known to the configuration class MetaClass metaConfig = MetaClass.forClass(Configuration.class); for (Object key : props.keySet()) { //严重参数是否合法 if (!metaConfig.hasSetter(String.valueOf(key))) { throw new BuilderException("The setting " + key + " is not known. Make sure you spelled it correctly (case sensitive)."); } } configuration.setAutoMappingBehavior(AutoMappingBehavior.valueOf(stringValueOf(props.getProperty("autoMappingBehavior"), "PARTIAL"))); configuration.setCacheEnabled(booleanValueOf(props.getProperty("cacheEnabled"), true)); configuration.setLazyLoadingEnabled(booleanValueOf(props.getProperty("lazyLoadingEnabled"), false)); configuration.setAggressiveLazyLoading(booleanValueOf(props.getProperty("aggressiveLazyLoading"), true)); configuration.setMultipleResultSetsEnabled(booleanValueOf(props.getProperty("multipleResultSetsEnabled"), true)); configuration.setUseColumnLabel(booleanValueOf(props.getProperty("useColumnLabel"), true)); configuration.setUseGeneratedKeys(booleanValueOf(props.getProperty("useGeneratedKeys"), false)); configuration.setDefaultExecutorType(ExecutorType.valueOf(stringValueOf(props.getProperty("defaultExecutorType"), "SIMPLE"))); configuration.setDefaultStatementTimeout(integerValueOf(props.getProperty("defaultStatementTimeout"), null)); } }
环境解析
private void environmentsElement(XNode context) throws Exception { if (context != null) { if (environment == null) { environment = context.getStringAttribute("default"); } for (XNode child : context.getChildren()) { String id = child.getStringAttribute("id"); if (isSpecifiedEnvironment(id)) { TransactionFactory txFactory = transactionManagerElement(child.evalNode("transactionManager")); DataSourceFactory dsFactory = dataSourceElement(child.evalNode("dataSource")); Environment.Builder environmentBuilder = new Environment.Builder(id) .transactionFactory(txFactory) .dataSource(dsFactory.getDataSource()); configuration.setEnvironment(environmentBuilder.build()); } } } }
环境解析
rivate void environmentsElement(XNode context) throws Exception { if (context != null) { if (environment == null) { environment = context.getStringAttribute("default"); } for (XNode child : context.getChildren()) { String id = child.getStringAttribute("id"); if (isSpecifiedEnvironment(id)) { //事物管理器 TransactionFactory txFactory = transactionManagerElement(child.evalNode("transactionManager")); //数据源 DataSourceFactory dsFactory = dataSourceElement(child.evalNode("dataSource")); Environment.Builder environmentBuilder = new Environment.Builder(id) .transactionFactory(txFactory) .dataSource(dsFactory.getDataSource()); configuration.setEnvironment(environmentBuilder.build()); } } } }
类型处理器解析
private void typeHandlerElement(XNode parent) throws Exception { if (parent != null) { for (XNode child : parent.getChildren()) { String javaType = child.getStringAttribute("javaType"); String jdbcType = child.getStringAttribute("jdbcType"); String handler = child.getStringAttribute("handler"); Class<?> javaTypeClass = resolveClass(javaType); TypeHandler typeHandlerInstance = (TypeHandler) resolveClass(handler).newInstance(); //也是解析后放在hashmap里 // private final Map<Class<?>, Map<JdbcType, TypeHandler>> TYPE_HANDLER_MAP = new HashMap<Class<?>, Map<JdbcType, TypeHandler>>(); if (jdbcType == null) { typeHandlerRegistry.register(javaTypeClass, typeHandlerInstance); } else { typeHandlerRegistry.register(javaTypeClass, resolveJdbcType(jdbcType), typeHandlerInstance); } } } }
mapper映射文件
private void mapperElement(XNode parent) throws Exception { if (parent != null) { for (XNode child : parent.getChildren()) { String resource = child.getStringAttribute("resource"); String url = child.getStringAttribute("url"); InputStream inputStream; if (resource != null && url == null) { ErrorContext.instance().resource(resource); inputStream = Resources.getResourceAsStream(resource); //构建mapper xml 解析 XMLMapperBuilder mapperParser = new XMLMapperBuilder(inputStream, configuration, resource, configuration.getSqlFragments()); mapperParser.parse(); } else if (url != null && resource == null) { ErrorContext.instance().resource(url); inputStream = Resources.getUrlAsStream(url); XMLMapperBuilder mapperParser = new XMLMapperBuilder(inputStream, configuration, url, configuration.getSqlFragments()); mapperParser.parse(); } else { throw new BuilderException("A mapper element may only specify a url or resource, but not both."); } } } } public void parse() { //判断是否已经解析过 if (!configuration.isResourceLoaded(resource)) { //获取mapper 跟节点并解析 configurationElement(parser.evalNode("/mapper")); //表示此resource已经解析 configuration.addLoadedResource(resource); //根据mapper的配置文件命名空间,查找对应的mapper类 bindMapperForNamespace(); } parsePendingChacheRefs(); parsePendingStatements(); } private void configurationElement(XNode context) { try { String namespace = context.getStringAttribute("namespace"); builderAssistant.setCurrentNamespace(namespace); cacheRefElement(context.evalNode("cache-ref")); cacheElement(context.evalNode("cache")); parameterMapElement(context.evalNodes("/mapper/parameterMap")); resultMapElements(context.evalNodes("/mapper/resultMap")); sqlElement(context.evalNodes("/mapper/sql")); buildStatementFromContext(context.evalNodes("select|insert|update|delete")); } catch (Exception e) { throw new RuntimeException("Error parsing Mapper XML. Cause: " + e, e); } }
相关推荐
总结起来,MyBatis源码分析涵盖了从配置加载到数据库操作的全过程,涉及到了配置解析、SQL执行、结果映射等多个关键环节,以及Executor、StatementHandler等核心组件。通过深入学习MyBatis的源码,开发者不仅可以...
源码分析将涵盖`ApplicationContext`的初始化过程,AOP(面向切面编程)的实现,以及事件传播机制。通过对这些核心组件的了解,可以提高你的Spring应用性能和可维护性。 SpringMVC作为Spring框架的一部分,负责处理...
SqlSessionFactory根据配置文件(如mybatis-config.xml)初始化,提供了一种线程安全的方式来获取SqlSession,后者是执行SQL命令的接口。 在执行SQL时,MyBatis的Executor执行器起着核心作用。它有SimpleExecutor、...
本系列源码解析的方式将从 MyBatis 的源码入手,深入分析 MyBatis 的设计思路和实现机制。 2. 容器的加载与初始化 2.1 config 文件解析 XMLConfigBuilder.parseConfiguration 方法是 MyBatis 中的核心方法之一,...
《MyBatis源码分析与实战应用》 在IT行业中,MyBatis作为一个轻量级的持久层框架,因其灵活性和高效性而被广泛应用。它将SQL语句与Java代码相结合,提供了比传统JDBC更方便的数据操作方式。本文将深入探讨MyBatis的...
### Mybatis源码分析 #### 1. 解析配置文件,创建SQLSessionFactory 在MyBatis框架中,创建`SQLSessionFactory`是初始化整个框架的重要步骤之一。这一过程涉及到了配置文件的读取与解析,以及如何构建出可以用于...
首先,MyBatis的初始化过程始于`SqlSessionFactoryBuilder`,它负责读取配置文件,构建`SqlSessionFactory`。配置文件通常包含数据源信息、Mapper XML文件的位置以及MyBatis全局设置。`SqlSessionFactory`是整个...
在分析MyBatis源码时,可以采用宏观和微观两种视角。宏观上理解整个框架的架构和流程,微观上深入到具体的类和方法,通过阅读和调试代码来理解其实现细节。同时,绘制流程图或UML图能帮助更好地梳理组件间的交互。 ...
在初版实现中,我们可以关注如何初始化 SqlSessionFactory,这通常涉及读取 mybatis-config.xml 文件,创建 Configuration 实例,然后通过 SqlSessionFactoryBuilder 创建 SqlSessionFactory。 4. **再来一个 2.0 ...
对MyBatis源码的分析通常从XML配置文件解析开始,这是整个框架初始化的关键步骤。主要关注以下两个切入点: - **XMLConfigBuilder#parseConfiguration**:解析mybatis-config.xml文件,生成Configuration对象,...
MyBatis源码自动生成工具是一款实用的开发辅助软件,专为简化MyBatis框架的初始化工作而设计。它能够帮助开发者快速生成包括XML配置文件和对应的Java类在内的基础架构代码,极大地提高了开发效率,降低了出错的可能...
【描述】"Mybatis系列教程Mybatis源码剖析共15页.pdf.zip" 是一个压缩文件,包含了15页关于Mybatis源码分析的教程内容。通过解压这个.zip文件,用户可以获取到PDF格式的教程文档,便于学习和查阅。这15页的内容通常...
- **使用场景:**在应用程序启动时通过配置文件或者直接指定配置的方式初始化。 **2. SqlSessionFactory:** - **功能:**用于创建SqlSession的工厂类。 - **使用场景:**每次需要操作数据库时,都需要通过...
通过对Mybatis源码的阅读和项目实践,我们可以更深入地了解其工作原理,提升我们的编程技巧,更好地利用Mybatis进行数据库操作。同时,对设计模式的理解也有助于我们编写出更加灵活、可维护的代码。
本次分享的项目《基于Java的HBNU后端学习之SpringBoot、Hibernate及MyBatis源码解析》为我们提供了一个深入了解这些框架内部工作机制的窗口。 该项目详细记录了湖北师范大学后端开发团队在实际开发中对SpringBoot、...
1. **SqlSessionFactoryBuilder**:Mybatis的初始化始于`SqlSessionFactoryBuilder`,它负责读取配置文件(XML或Java Config),构建`SqlSessionFactory`。这个过程包括解析配置、加载映射文件、创建Configuration...
MyBatis是一个流行的Java持久层框架,它简化了数据库操作,允许开发者将SQL查询与Java代码直接集成。...在源码分析中,对这两个组件的深入理解可以帮助开发者优化性能,排查问题,以及自定义扩展MyBatis的功能。
- `SqlSessionFactoryBuilder`: 用于构建 `SqlSessionFactory`,它是 MyBatis 的核心,负责初始化和配置 MyBatis。 - `SqlSessionFactory`: 会话工厂,用于创建 `SqlSession` 对象,`SqlSession` 是执行 SQL 的...
源码分析方面,MyBatis源码主要由以下几个核心组件构成: 1. SqlSessionFactoryBuilder:用于构建SqlSessionFactory实例,它是一个工厂模式的应用,其目的是为了创建SqlSession实例。 2. SqlSessionFactory:一个...
在深入探讨MyBatis源码之前,先要理解MyBatis的基本概念和工作原理。 MyBatis的核心组件包括SqlSession、SqlSessionFactory和Mapper。SqlSession是与数据库交互的会话对象,用于执行SQL命令;SqlSessionFactory则是...