myBatis源码之XMLConfigBuilder
来源:互联网 发布:数据恢复软件的应用 编辑:程序博客网 时间:2024/05/21 18:36
XMLConfigBuilder是对mybatis的配置文件进行解析的类,会对myabtis解析后的信息存放在Configuration对象中,Configuration对象会贯穿整个mybatis的执行流程,为mybatis的执行过程提供各种需要的配置信息。
/** * @author Clinton Begin */public class XMLConfigBuilder extends BaseBuilder { private boolean parsed; private XPathParser parser; private String environment; public XMLConfigBuilder(Reader reader) { this(reader, null, null); } public XMLConfigBuilder(Reader reader, String environment) { this(reader, environment, null); } public XMLConfigBuilder(Reader reader, String environment, Properties props) { this(new XPathParser(reader, true, props, new XMLMapperEntityResolver()), environment, props); } public XMLConfigBuilder(InputStream inputStream) { this(inputStream, null, null); } public XMLConfigBuilder(InputStream inputStream, String environment) { this(inputStream, environment, null); } public XMLConfigBuilder(InputStream inputStream, String environment, Properties props) { this(new XPathParser(inputStream, true, props, new XMLMapperEntityResolver()), environment, props); } private XMLConfigBuilder(XPathParser parser, String environment, Properties props) { super(new Configuration()); ErrorContext.instance().resource("SQL Mapper Configuration"); this.configuration.setVariables(props); this.parsed = false; this.environment = environment; this.parser = parser; } public Configuration parse() { if (parsed) { throw new BuilderException("Each XMLConfigBuilder can only be used once."); } parsed = true;//mybatis的配置文件的根节点是configuration,从根节点开始解析配置文件 parseConfiguration(parser.evalNode("/configuration")); return configuration; } private void parseConfiguration(XNode root) { try { //解析子节点properties propertiesElement(root.evalNode("properties")); //issue #117 read properties first //解析子节点typeAliases 别名 typeAliasesElement(root.evalNode("typeAliases")); //解析子节点plugins 插件 pluginElement(root.evalNode("plugins")); //解析子节点objectFactory mybatis为结果创建对象时都会用到objectFactory objectFactoryElement(root.evalNode("objectFactory")); //解析子节点objectWrapperFactory objectWrapperFactoryElement(root.evalNode("objectWrapperFactory")); //解析settings定义一些全局性的配置 settingsElement(root.evalNode("settings")); //解析environments 可以配置多个运行环境,但是每个SqlSessionFactory 实例只能选择一个运行环境 environmentsElement(root.evalNode("environments")); // read it after objectFactory and objectWrapperFactory issue #631 //解析databaseIdProvider MyBatis能够执行不同的语句取决于你提供的数据库供应商。许多数据库供应商的支持是基于databaseId映射 databaseIdProviderElement(root.evalNode("databaseIdProvider")); //解析typeHandlers 当MyBatis设置参数到PreparedStatement 或者从ResultSet 结果集中取得值时,就会使用TypeHandler 来处理数据库类型与java 类型之间转换 typeHandlerElement(root.evalNode("typeHandlers")); //解析mappers 主要的crud操作都是在mappers中定义的 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()) {//如果子节点是package,那么就获取package节点的name属性 if ("package".equals(child.getName())) { String typeAliasPackage = child.getStringAttribute("name"); configuration.getTypeAliasRegistry().registerAliases(typeAliasPackage); } else {//如果子节点是typeAlias节点,那么就获取alias属性和type的属性 String alias = child.getStringAttribute("alias"); String type = child.getStringAttribute("type"); try {//通过type的值来加载获得类 Class<?> clazz = Resources.classForName(type); if (alias == null) {//typeAliasRegistry会进行别名注册 typeAliasRegistry.registerAlias(clazz); } else { typeAliasRegistry.registerAlias(alias, clazz); } } catch (ClassNotFoundException e) { throw new BuilderException("Error registering typeAlias for '" + alias + "'. Cause: " + e, e); } } } } } //插件元素解析 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.addInterceptor(interceptorInstance); } } } //对象工厂元素解析 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); configuration.setObjectFactory(factory); } } //对象打包工厂元素解析 private void objectWrapperFactoryElement(XNode context) throws Exception { if (context != null) { String type = context.getStringAttribute("type"); ObjectWrapperFactory factory = (ObjectWrapperFactory) resolveClass(type).newInstance(); configuration.setObjectWrapperFactory(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); } } //配置元素解析 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(props.getProperty("autoMappingBehavior", "PARTIAL"))); configuration.setCacheEnabled(booleanValueOf(props.getProperty("cacheEnabled"), true)); configuration.setProxyFactory((ProxyFactory) createInstance(props.getProperty("proxyFactory"))); 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(props.getProperty("defaultExecutorType", "SIMPLE"))); configuration.setDefaultStatementTimeout(integerValueOf(props.getProperty("defaultStatementTimeout"), null)); configuration.setMapUnderscoreToCamelCase(booleanValueOf(props.getProperty("mapUnderscoreToCamelCase"), false)); configuration.setSafeRowBoundsEnabled(booleanValueOf(props.getProperty("safeRowBoundsEnabled"), false)); configuration.setLocalCacheScope(LocalCacheScope.valueOf(props.getProperty("localCacheScope", "SESSION"))); configuration.setJdbcTypeForNull(JdbcType.valueOf(props.getProperty("jdbcTypeForNull", "OTHER"))); configuration.setLazyLoadTriggerMethods(stringSetValueOf(props.getProperty("lazyLoadTriggerMethods"), "equals,clone,hashCode,toString")); configuration.setSafeResultHandlerEnabled(booleanValueOf(props.getProperty("safeResultHandlerEnabled"), true)); configuration.setDefaultScriptingLanguage(resolveClass(props.getProperty("defaultScriptingLanguage"))); configuration.setCallSettersOnNulls(booleanValueOf(props.getProperty("callSettersOnNulls"), false)); configuration.setLogPrefix(props.getProperty("logPrefix")); configuration.setLogImpl(resolveClass(props.getProperty("logImpl"))); configuration.setConfigurationFactory(resolveClass(props.getProperty("configurationFactory"))); } } //环境元素解析 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")); DataSource dataSource = dsFactory.getDataSource(); Environment.Builder environmentBuilder = new Environment.Builder(id) .transactionFactory(txFactory) .dataSource(dataSource); configuration.setEnvironment(environmentBuilder.build()); } } } } //解析databaseIdProvider MyBatis能够执行不同的语句取决于你提供的数据库供应商。许多数据库供应商的支持是基于databaseId映射 private void databaseIdProviderElement(XNode context) throws Exception { DatabaseIdProvider databaseIdProvider = null; if (context != null) { String type = context.getStringAttribute("type"); if ("VENDOR".equals(type)) type = "DB_VENDOR"; // awful patch to keep backward compatibility Properties properties = context.getChildrenAsProperties(); databaseIdProvider = (DatabaseIdProvider) resolveClass(type).newInstance(); databaseIdProvider.setProperties(properties); } Environment environment = configuration.getEnvironment(); if (environment != null && databaseIdProvider != null) { String databaseId = databaseIdProvider.getDatabaseId(environment.getDataSource()); configuration.setDatabaseId(databaseId); } } //事务配置解析,获得事务工厂(JDBC和MANAGED两种) private TransactionFactory transactionManagerElement(XNode context) throws Exception { if (context != null) { String type = context.getStringAttribute("type"); Properties props = context.getChildrenAsProperties(); TransactionFactory factory = (TransactionFactory) resolveClass(type).newInstance(); factory.setProperties(props); return factory; } throw new BuilderException("Environment declaration requires a TransactionFactory."); } //数据源解析获得数据源工厂 private DataSourceFactory dataSourceElement(XNode context) throws Exception { if (context != null) { String type = context.getStringAttribute("type"); Properties props = context.getChildrenAsProperties(); DataSourceFactory factory = (DataSourceFactory) resolveClass(type).newInstance(); factory.setProperties(props); return factory; } throw new BuilderException("Environment declaration requires a DataSourceFactory."); } //类型控制元素解析,数据库数据类型和Java数据类型的解析 private void typeHandlerElement(XNode parent) throws Exception { if (parent != null) { for (XNode child : parent.getChildren()) { if ("package".equals(child.getName())) { String typeHandlerPackage = child.getStringAttribute("name"); typeHandlerRegistry.register(typeHandlerPackage); } else { String javaTypeName = child.getStringAttribute("javaType"); String jdbcTypeName = child.getStringAttribute("jdbcType"); String handlerTypeName = child.getStringAttribute("handler"); Class<?> javaTypeClass = resolveClass(javaTypeName); JdbcType jdbcType = resolveJdbcType(jdbcTypeName); Class<?> typeHandlerClass = resolveClass(handlerTypeName); if (javaTypeClass != null) { if (jdbcType == null) { typeHandlerRegistry.register(javaTypeClass, typeHandlerClass); } else { typeHandlerRegistry.register(javaTypeClass, jdbcType, typeHandlerClass); } } else { typeHandlerRegistry.register(typeHandlerClass); } } } } } //mapper元素解析,获得各种crud操作或者配置文件 private void mapperElement(XNode parent) throws Exception { if (parent != null) { for (XNode child : parent.getChildren()) { if ("package".equals(child.getName())) { String mapperPackage = child.getStringAttribute("name"); configuration.addMappers(mapperPackage); } else { String resource = child.getStringAttribute("resource"); String url = child.getStringAttribute("url"); String mapperClass = child.getStringAttribute("class"); if (resource != null && url == null && mapperClass == null) { ErrorContext.instance().resource(resource); InputStream inputStream = Resources.getResourceAsStream(resource); XMLMapperBuilder mapperParser = new XMLMapperBuilder(inputStream, configuration, resource, configuration.getSqlFragments()); mapperParser.parse(); } else if (resource == null && url != null && mapperClass == null) { ErrorContext.instance().resource(url); InputStream inputStream = Resources.getUrlAsStream(url); XMLMapperBuilder mapperParser = new XMLMapperBuilder(inputStream, configuration, url, configuration.getSqlFragments()); mapperParser.parse(); } else if (resource == null && url == null && mapperClass != null) { Class<?> mapperInterface = Resources.classForName(mapperClass); configuration.addMapper(mapperInterface); } else { throw new BuilderException("A mapper element may only specify a url, resource or class, but not more than one."); } } } } } private boolean isSpecifiedEnvironment(String id) { if (environment == null) { throw new BuilderException("No environment specified."); } else if (id == null) { throw new BuilderException("Environment requires an id attribute."); } else if (environment.equals(id)) { return true; } return false; }}
0 0
- myBatis源码之XMLConfigBuilder
- MyBatis-1-XMLConfigBuilder
- Mybatis3源码分析(02)-加载Configuration-XMLConfigBuilder
- myBatis源码之Configuration
- mybatis源码之MapperMethod
- mybatis源码之StatementHandler
- mybatis源码之BaseStatementHandler
- Mybatis源码之CallableStatementHandler
- mybatis源码之PreparedStatementHandler
- Mybatis源码之RoutingStatementHandler
- mybatis源码之SimpleStatementHandler
- Mybatis源码之SimpleExecutor
- myBatis源码之BatchExecutor
- 读mybatis源码之十四:mybatis事务处理
- myBatis源码学习之SqlSessionFactoryBuilder
- myBatis源码学习之SqlSessionFactory
- myBatis源码学习之SqlSession
- Mybatis源码分析之缓存
- window 下 MySQL免安装使用
- 第十三周 Floyd算法验证
- 数据结构:二叉树
- EL1041E:(pos 2): After parsing a valid expression
- YiiBooster使用:booster.helpers.TbHtml的AjaxSubmitButton bug修复
- myBatis源码之XMLConfigBuilder
- Invalid MEX-file: caffe.mexa64 的解决方案
- 【splay】BZOJ 1503 郁闷的出纳员
- js模拟php的shuffle函数,用来打乱一维数组
- C#类型基础----对象判等
- Eclipse中10个最有用的快捷键组合
- myBatis源码之Configuration
- div+css清除浮动
- C++ 学习第三天