- 浏览: 984905 次
文章分类
- 全部博客 (428)
- Hadoop (2)
- HBase (1)
- ELK (1)
- ActiveMQ (13)
- Kafka (5)
- Redis (14)
- Dubbo (1)
- Memcached (5)
- Netty (56)
- Mina (34)
- NIO (51)
- JUC (53)
- Spring (13)
- Mybatis (17)
- MySQL (21)
- JDBC (12)
- C3P0 (5)
- Tomcat (13)
- SLF4J-log4j (9)
- P6Spy (4)
- Quartz (12)
- Zabbix (7)
- JAVA (9)
- Linux (15)
- HTML (9)
- Lucene (0)
- JS (2)
- WebService (1)
- Maven (4)
- Oracle&MSSQL (14)
- iText (11)
- Development Tools (8)
- UTILS (4)
- LIFE (8)
最新评论
-
Donald_Draper:
Donald_Draper 写道刘落落cici 写道能给我发一 ...
DatagramChannelImpl 解析三(多播) -
Donald_Draper:
刘落落cici 写道能给我发一份这个类的源码吗Datagram ...
DatagramChannelImpl 解析三(多播) -
lyfyouyun:
请问楼主,执行消息发送的时候,报错:Transport sch ...
ActiveMQ连接工厂、连接详解 -
ezlhq:
关于 PollArrayWrapper 状态含义猜测:参考 S ...
WindowsSelectorImpl解析一(FdMap,PollArrayWrapper) -
flyfeifei66:
打算使用xmemcache作为memcache的客户端,由于x ...
Memcached分布式客户端(Xmemcached)
mybatis 使用教程:http://donald-draper.iteye.com/blog/2330429
Mybatis加载解析Mapper(xml)文件第一讲:http://donald-draper.iteye.com/blog/2333125
Mybatis加载解析Mapper(xml)文件第二讲:http://donald-draper.iteye.com/blog/2333191
在使用教程,我们有一个静态方法,初始化SqlSessionFactory
这篇文章,主要解决SqlSessionFactory是如何初始化的问题?我们从这一句开始
先看解析配置文件
//Mybatis配置项
//BaseBuilder
来看new XPathParser(reader, true, props, new XMLMapperEntityResolver()这一句构造XPathParser
//XNode
现在回到XMLConfigBuilder的解析mybatisConfig.xml文件
下面依次来看properties,typeAliases,plugins,objectFactory,objectWrapperFactory
,settings,environments,databaseIdProvider,typeHandlers,mappers的解析初始化
初始化properties
在XMLConfigBuilder的构造函数中初始化过Variables,首先加载properties标签中
resource为Properties,如果在构造SqlSessionFactoryBuilder
(sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader))
的过程中,传入了Properties文件,
则覆盖掉resource的Properties。
初始化typeAliases
//TypeAliasRegistry
//初始化plugins
来看插件的添加
//Configuration
//InterceptorChain
//Interceptor
//初始化ObjectFactory
//ObjectFactory
//初始化ObjectWrapperFactory
//ObjectWrapperFactory
//初始化settings
//初始化environments
//Environment
初始化typeHandler
//TypeHandlerRegistry
//TypeHandler
//JdbcType
从上面可以看出;初始化typeHandler,就是初始化javaType,jdbcType,及TypeHandler的映射关系
初始化mappers
回到SqlSessionFactoryBuilder,可以看到builder实际上是返回的是DefaultSqlSessionFactory
总结:
从上,可以出SqlSessionFactoryBuilder做的主要工作是,加载全局配置文件,根据
properties,typeAliases,plugins,objectFactory,objectWrapperFactory
,settings,environments,databaseIdProvider,typeHandlers,mappers配置项,
初始化Configuration,由于mappers解析内容较多,我们放在下一篇来讲。
附:Mapper解析的引篇
//Configuration
//MapperRegistry
//MapperProxyFactory
//MapperProxy
从上可以看出Configuration添加MapperInterface,就是MapperRegistry注册到其
HashMap<Class,MapperProxyFactory>中,MapperProxyFactory是MapperInterface的代理,
生成MapperInterface的MapperProxy代理实例,MapperProxy中利用Map<Method,MapperMethod>,
实现二级缓存
//MapperAnnotationBuilder,MapperInterface的注解处理
Mybatis加载解析Mapper(xml)文件第一讲:http://donald-draper.iteye.com/blog/2333125
Mybatis加载解析Mapper(xml)文件第二讲:http://donald-draper.iteye.com/blog/2333191
在使用教程,我们有一个静态方法,初始化SqlSessionFactory
static{ try{ reader = Resources.getResourceAsReader("mybatisConfig.xml"); sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader); } }
这篇文章,主要解决SqlSessionFactory是如何初始化的问题?我们从这一句开始
sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader) public class SqlSessionFactoryBuilder { public SqlSessionFactory build(Reader reader) { return build(reader, null, null); } //创建SqlSessionFactory public SqlSessionFactory build(Reader reader, String environment, Properties properties) { SqlSessionFactory sqlsessionfactory; try { //解析配置文件 XMLConfigBuilder parser = new XMLConfigBuilder(reader, environment, properties); //根据Configuration,创建sqlsessionfactory sqlsessionfactory = build(parser.parse()); } catch(Exception e) { throw ExceptionFactory.wrapException("Error building SqlSession.", e); } ErrorContext.instance().reset(); } //根据Configuration,创建sqlsessionfactory public SqlSessionFactory build(Configuration config) { return new DefaultSqlSessionFactory(config); } }
先看解析配置文件
public class XMLConfigBuilder extends BaseBuilder { private boolean parsed;//解析状态 private XPathParser parser; private String environment;//环境 public XMLConfigBuilder(Reader reader, String environment, Properties props) { this(new XPathParser(reader, true, props, new XMLMapperEntityResolver()), environment, props); } //初始化XMLConfigBuilder private XMLConfigBuilder(XPathParser parser, String environment, Properties props) { super(new Configuration()); ErrorContext.instance().resource("SQL Mapper Configuration"); configuration.setVariables(props); parsed = false; this.environment = environment; this.parser = parser; } //获取配置信息Configuration public Configuration parse() { if(parsed) { throw new BuilderException("Each MapperConfigParser can only be used once."); } else { parsed = true; //解析mybatisConfig.xml文件 parseConfiguration(parser.evalNode("/configuration")); return configuration; } } //解析mybatisConfig.xml文件,properties,typeAliases,plugins,objectFactory,objectWrapperFactory //settings,environments,databaseIdProvider,typeHandlers,mappers private void parseConfiguration(XNode root) { try { propertiesElement(root.evalNode("properties")); typeAliasesElement(root.evalNode("typeAliases")); pluginElement(root.evalNode("plugins")); objectFactoryElement(root.evalNode("objectFactory")); objectWrapperFactoryElement(root.evalNode("objectWrapperFactory")); settingsElement(root.evalNode("settings")); environmentsElement(root.evalNode("environments")); databaseIdProviderElement(root.evalNode("databaseIdProvider")); typeHandlerElement(root.evalNode("typeHandlers")); mapperElement(root.evalNode("mappers")); } catch(Exception e) { throw new BuilderException((new StringBuilder()).append("Error parsing SQL Mapper Configuration. Cause: ").append(e).toString(), e); } } }
//Mybatis配置项
public class Configuration{ protected Environment environment;//环境 protected boolean safeRowBoundsEnabled; protected boolean safeResultHandlerEnabled; protected boolean mapUnderscoreToCamelCase; protected boolean aggressiveLazyLoading; protected boolean multipleResultSetsEnabled; protected boolean useGeneratedKeys;//允许JDBC支持生成的键 protected boolean useColumnLabel; protected boolean cacheEnabled;//全局的映射器启用或禁用缓存 protected boolean callSettersOnNulls; protected String logPrefix; protected Class logImpl; protected LocalCacheScope localCacheScope;//本地一级缓存作用域 protected JdbcType jdbcTypeForNull; protected Set lazyLoadTriggerMethods; protected Integer defaultStatementTimeout; protected ExecutorType defaultExecutorType; protected AutoMappingBehavior autoMappingBehavior; protected Properties variables; protected ObjectFactory objectFactory; protected ObjectWrapperFactory objectWrapperFactory; protected MapperRegistry mapperRegistry; protected boolean lazyLoadingEnabled; protected ProxyFactory proxyFactory; protected String databaseId; protected final InterceptorChain interceptorChain;//插件链 protected final TypeHandlerRegistry typeHandlerRegistry;//类型处理注册器 protected final TypeAliasRegistry typeAliasRegistry;//类型别名注册器 protected final LanguageDriverRegistry languageRegistry; protected final Map mappedStatements;// protected final Map caches; protected final Map resultMaps; protected final Map parameterMaps; protected final Map keyGenerators; protected final Set loadedResources; protected final Map sqlFragments; protected final Collection incompleteStatements; protected final Collection incompleteCacheRefs; protected final Collection incompleteResultMaps; protected final Collection incompleteMethods; protected final Map cacheRefMap; //初始化配置项 public Configuration() { safeRowBoundsEnabled = false; safeResultHandlerEnabled = true; mapUnderscoreToCamelCase = false; aggressiveLazyLoading = true; multipleResultSetsEnabled = true; useGeneratedKeys = false;//允许JDBC支持生成的键 useColumnLabel = true; cacheEnabled = true;//全局的映射器启用或禁用缓存 callSettersOnNulls = false; localCacheScope = LocalCacheScope.SESSION;//本地一级缓存作用域 jdbcTypeForNull = JdbcType.OTHER; lazyLoadTriggerMethods = new HashSet(Arrays.asList(new String[] { "equals", "clone", "hashCode", "toString" })); defaultExecutorType = ExecutorType.SIMPLE; autoMappingBehavior = AutoMappingBehavior.PARTIAL; variables = new Properties(); objectFactory = new DefaultObjectFactory(); objectWrapperFactory = new DefaultObjectWrapperFactory(); mapperRegistry = new MapperRegistry(this); lazyLoadingEnabled = false; interceptorChain = new InterceptorChain();//插件链 typeHandlerRegistry = new TypeHandlerRegistry();//类型处理注册器 typeAliasRegistry = new TypeAliasRegistry();//类型别名注册器 languageRegistry = new LanguageDriverRegistry(); mappedStatements = new StrictMap("Mapped Statements collection"); caches = new StrictMap("Caches collection"); resultMaps = new StrictMap("Result Maps collection"); parameterMaps = new StrictMap("Parameter Maps collection"); keyGenerators = new StrictMap("Key Generators collection"); loadedResources = new HashSet(); sqlFragments = new StrictMap("XML fragments parsed from previous mappers"); incompleteStatements = new LinkedList(); incompleteCacheRefs = new LinkedList(); incompleteResultMaps = new LinkedList(); incompleteMethods = new LinkedList(); cacheRefMap = new HashMap(); typeAliasRegistry.registerAlias("JDBC", org/apache/ibatis/transaction/jdbc/JdbcTransactionFactory); typeAliasRegistry.registerAlias("MANAGED", org/apache/ibatis/transaction/managed/ManagedTransactionFactory); typeAliasRegistry.registerAlias("JNDI", org/apache/ibatis/datasource/jndi/JndiDataSourceFactory); typeAliasRegistry.registerAlias("POOLED", org/apache/ibatis/datasource/pooled/PooledDataSourceFactory); typeAliasRegistry.registerAlias("UNPOOLED", org/apache/ibatis/datasource/unpooled/UnpooledDataSourceFactory); typeAliasRegistry.registerAlias("PERPETUAL", org/apache/ibatis/cache/impl/PerpetualCache); typeAliasRegistry.registerAlias("FIFO", org/apache/ibatis/cache/decorators/FifoCache); typeAliasRegistry.registerAlias("LRU", org/apache/ibatis/cache/decorators/LruCache); typeAliasRegistry.registerAlias("SOFT", org/apache/ibatis/cache/decorators/SoftCache); typeAliasRegistry.registerAlias("WEAK", org/apache/ibatis/cache/decorators/WeakCache); typeAliasRegistry.registerAlias("VENDOR", org/apache/ibatis/mapping/VendorDatabaseIdProvider); typeAliasRegistry.registerAlias("XML", org/apache/ibatis/scripting/xmltags/XMLLanguageDriver); typeAliasRegistry.registerAlias("RAW", org/apache/ibatis/scripting/defaults/RawLanguageDriver); typeAliasRegistry.registerAlias("SLF4J", org/apache/ibatis/logging/slf4j/Slf4jImpl); typeAliasRegistry.registerAlias("COMMONS_LOGGING", org/apache/ibatis/logging/commons/JakartaCommonsLoggingImpl); typeAliasRegistry.registerAlias("LOG4J", org/apache/ibatis/logging/log4j/Log4jImpl); typeAliasRegistry.registerAlias("JDK_LOGGING", org/apache/ibatis/logging/jdk14/Jdk14LoggingImpl); typeAliasRegistry.registerAlias("STDOUT_LOGGING", org/apache/ibatis/logging/stdout/StdOutImpl); typeAliasRegistry.registerAlias("NO_LOGGING", org/apache/ibatis/logging/nologging/NoLoggingImpl); typeAliasRegistry.registerAlias("CGLIB", org/apache/ibatis/executor/loader/CglibProxyFactory); typeAliasRegistry.registerAlias("JAVASSIST", org/apache/ibatis/executor/loader/JavassistProxyFactory); languageRegistry.setDefaultDriverClass(org/apache/ibatis/scripting/xmltags/XMLLanguageDriver); languageRegistry.register(org/apache/ibatis/scripting/defaults/RawLanguageDriver); } //设置Configuration,属性变量variables public void setVariables(Properties variables) { this.variables = variables; } }
//BaseBuilder
public abstract class BaseBuilder { public BaseBuilder(Configuration configuration) { this.configuration = configuration; typeAliasRegistry = this.configuration.getTypeAliasRegistry(); typeHandlerRegistry = this.configuration.getTypeHandlerRegistry(); } protected final Configuration configuration;//Mybatis配置项 protected final TypeAliasRegistry typeAliasRegistry; protected final TypeHandlerRegistry typeHandlerRegistry; }
来看new XPathParser(reader, true, props, new XMLMapperEntityResolver()这一句构造XPathParser
public class XPathParser { private Document document;//文档 private boolean validation; private EntityResolver entityResolver;//实体解决器 private Properties variables; private XPath xpath; //构造XPathParser public XPathParser(Reader reader, boolean validation, Properties variables, EntityResolver entityResolver) { commonConstructor(validation, variables, entityResolver); document = createDocument(new InputSource(reader)); } //初始化entityResolver,xpath private void commonConstructor(boolean validation, Properties variables, EntityResolver entityResolver) { this.validation = validation; this.entityResolver = entityResolver; this.variables = variables; XPathFactory factory = XPathFactory.newInstance(); xpath = factory.newXPath(); } //创建Document private Document createDocument(InputSource inputSource) { DocumentBuilder builder; DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); factory.setValidating(validation); factory.setNamespaceAware(false); factory.setIgnoringComments(true); factory.setIgnoringElementContentWhitespace(false); factory.setCoalescing(false); factory.setExpandEntityReferences(true); builder = factory.newDocumentBuilder(); builder.setEntityResolver(entityResolver); builder.setErrorHandler(new ErrorHandler() { public void error(SAXParseException exception) throws SAXException { throw exception; } public void fatalError(SAXParseException exception) throws SAXException { throw exception; } public void warning(SAXParseException saxparseexception) throws SAXException { } final XPathParser this$0; { this$0 = XPathParser.this; super(); } }); return builder.parse(inputSource); Exception e; e; throw new BuilderException((new StringBuilder()).append("Error creating document instance. Cause: ").append(e).toString(), e); } //根据表达式返回document对应的XNode public XNode evalNode(String expression) { return evalNode(document, expression); } public XNode evalNode(Object root, String expression) { Node node = (Node)evaluate(expression, root, XPathConstants.NODE); if(node == null) return null; else return new XNode(this, node, variables); } private Object evaluate(String expression, Object root, QName returnType) { return xpath.evaluate(expression, root, returnType); } }
//XNode
public class XNode { public XNode(XPathParser xpathParser, Node node, Properties variables) { this.xpathParser = xpathParser; this.node = node; name = node.getNodeName(); this.variables = variables; attributes = parseAttributes(node); body = parseBody(node); } private Node node; private String name; private String body; private Properties attributes; private Properties variables; private XPathParser xpathParser; }
现在回到XMLConfigBuilder的解析mybatisConfig.xml文件
parseConfiguration(parser.evalNode("/configuration")); private void parseConfiguration(XNode root) { try { propertiesElement(root.evalNode("properties")); typeAliasesElement(root.evalNode("typeAliases")); pluginElement(root.evalNode("plugins")); objectFactoryElement(root.evalNode("objectFactory")); objectWrapperFactoryElement(root.evalNode("objectWrapperFactory")); settingsElement(root.evalNode("settings")); environmentsElement(root.evalNode("environments")); databaseIdProviderElement(root.evalNode("databaseIdProvider")); typeHandlerElement(root.evalNode("typeHandlers")); mapperElement(root.evalNode("mappers")); } }
下面依次来看properties,typeAliases,plugins,objectFactory,objectWrapperFactory
,settings,environments,databaseIdProvider,typeHandlers,mappers的解析初始化
初始化properties
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); } }
在XMLConfigBuilder的构造函数中初始化过Variables,首先加载properties标签中
resource为Properties,如果在构造SqlSessionFactoryBuilder
(sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader))
的过程中,传入了Properties文件,
则覆盖掉resource的Properties。
初始化typeAliases
private void typeAliasesElement(XNode parent) { if(parent != null) { for(Iterator i$ = parent.getChildren().iterator(); i$.hasNext();) { XNode child = (XNode)i$.next(); if("package".equals(child.getName())) { String typeAliasPackage = child.getStringAttribute("name"); configuration.getTypeAliasRegistry().registerAliases(typeAliasPackage); } else { 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); } } } } }
//TypeAliasRegistry
public class TypeAliasRegistry { //实际上类型别名是存储在一个Map中 //HashMap<String,Classs>,key为alias,Class为类Type private final HashMap TYPE_ALIASES = new HashMap(); public TypeAliasRegistry() { //系统默认类型别名 registerAlias("string", java/lang/String); registerAlias("byte", java/lang/Byte); registerAlias("long", java/lang/Long); registerAlias("short", java/lang/Short); registerAlias("int", java/lang/Integer); registerAlias("integer", java/lang/Integer); registerAlias("double", java/lang/Double); registerAlias("float", java/lang/Float); registerAlias("boolean", java/lang/Boolean); registerAlias("byte[]", [Ljava/lang/Byte;); registerAlias("long[]", [Ljava/lang/Long;); registerAlias("short[]", [Ljava/lang/Short;); registerAlias("int[]", [Ljava/lang/Integer;); registerAlias("integer[]", [Ljava/lang/Integer;); registerAlias("double[]", [Ljava/lang/Double;); registerAlias("float[]", [Ljava/lang/Float;); registerAlias("boolean[]", [Ljava/lang/Boolean;); registerAlias("_byte", Byte.TYPE); registerAlias("_long", Long.TYPE); registerAlias("_short", Short.TYPE); registerAlias("_int", Integer.TYPE); registerAlias("_integer", Integer.TYPE); registerAlias("_double", Double.TYPE); registerAlias("_float", Float.TYPE); registerAlias("_boolean", Boolean.TYPE); registerAlias("_byte[]", [B); registerAlias("_long[]", [J); registerAlias("_short[]", [S); registerAlias("_int[]", [I); registerAlias("_integer[]", [I); registerAlias("_double[]", [D); registerAlias("_float[]", [F); registerAlias("_boolean[]", [Z); registerAlias("date", java/util/Date); registerAlias("decimal", java/math/BigDecimal); registerAlias("bigdecimal", java/math/BigDecimal); registerAlias("biginteger", java/math/BigInteger); registerAlias("object", java/lang/Object); registerAlias("date[]", [Ljava/util/Date;); registerAlias("decimal[]", [Ljava/math/BigDecimal;); registerAlias("bigdecimal[]", [Ljava/math/BigDecimal;); registerAlias("biginteger[]", [Ljava/math/BigInteger;); registerAlias("object[]", [Ljava/lang/Object;); registerAlias("map", java/util/Map); registerAlias("hashmap", java/util/HashMap); registerAlias("list", java/util/List); registerAlias("arraylist", java/util/ArrayList); registerAlias("collection", java/util/Collection); registerAlias("iterator", java/util/Iterator); registerAlias("ResultSet", java/sql/ResultSet); } //类型别名注册器,注册类型别名 public void registerAlias(String alias, Class value) { if(alias == null) throw new TypeException("The parameter alias cannot be null"); String key = alias.toLowerCase(Locale.ENGLISH); if(TYPE_ALIASES.containsKey(key) && TYPE_ALIASES.get(key) != null && !((Class)TYPE_ALIASES.get(key)).equals(value)) { throw new TypeException((new StringBuilder()).append("The alias '").append(alias).append("' is already mapped to the value '").append(((Class)TYPE_ALIASES.get(key)).getName()).append("'.").toString()); } else { TYPE_ALIASES.put(key, value); return; } } }
//初始化plugins
private void pluginElement(XNode parent) throws Exception { if(parent != null) { Interceptor interceptorInstance; //添加插件configuration.addInterceptor(interceptorInstance) for(Iterator i$ = parent.getChildren().iterator(); i$.hasNext(); configuration.addInterceptor(interceptorInstance)) { XNode child = (XNode)i$.next(); //获取插件类 String interceptor = child.getStringAttribute("interceptor"); //获取插件属性 Properties properties = child.getChildrenAsProperties(); interceptorInstance = (Interceptor)resolveClass(interceptor).newInstance(); interceptorInstance.setProperties(properties); } } }
来看插件的添加
//Configuration
public void addInterceptor(Interceptor interceptor) { interceptorChain.addInterceptor(interceptor); }
//InterceptorChain
public class InterceptorChain { public Object pluginAll(Object target) { for(Iterator i$ = interceptors.iterator(); i$.hasNext();) { Interceptor interceptor = (Interceptor)i$.next(); target = interceptor.plugin(target); } return target; } public void addInterceptor(Interceptor interceptor) { interceptors.add(interceptor); } //实际上是添加到一个List<Interceptor>中 private final List interceptors = new ArrayList(); }
//Interceptor
public interface Interceptor { public abstract Object intercept(Invocation invocation) throws Throwable; public abstract Object plugin(Object obj); public abstract void setProperties(Properties properties); }
//初始化ObjectFactory
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); } }
//ObjectFactory
public interface ObjectFactory { public abstract void setProperties(Properties properties); public abstract Object create(Class class1); public abstract Object create(Class class1, List list, List list1); public abstract boolean isCollection(Class class1); }
//初始化ObjectWrapperFactory
private void objectWrapperFactoryElement(XNode context) throws Exception { if(context != null) { String type = context.getStringAttribute("type"); ObjectWrapperFactory factory = (ObjectWrapperFactory)resolveClass(type).newInstance(); configuration.setObjectWrapperFactory(factory); } }
//ObjectWrapperFactory
public interface ObjectWrapperFactory { public abstract boolean hasWrapperFor(Object obj); public abstract ObjectWrapper getWrapperFor(MetaObject metaobject, Object obj); }
//初始化settings
private void settingsElement(XNode context) throws Exception { if(context != null) { Properties props = context.getChildrenAsProperties(); MetaClass metaConfig = MetaClass.forClass(org/apache/ibatis/session/Configuration); for(Iterator i$ = props.keySet().iterator(); i$.hasNext();) { Object key = i$.next(); if(!metaConfig.hasSetter(String.valueOf(key))) throw new BuilderException((new StringBuilder()).append("The setting ").append(key).append(" is not known. Make sure you spelled it correctly (case sensitive).").toString()); } //配置configuration,是否懒加载,自动生成主键,全局映射缓存,本地以及缓存, configuration.setAutoMappingBehavior(AutoMappingBehavior.valueOf(props.getProperty("autoMappingBehavior", "PARTIAL"))); configuration.setCacheEnabled(booleanValueOf(props.getProperty("cacheEnabled"), Boolean.valueOf(true)).booleanValue()); //proxyFactory configuration.setProxyFactory((ProxyFactory)createInstance(props.getProperty("proxyFactory"))); configuration.setLazyLoadingEnabled(booleanValueOf(props.getProperty("lazyLoadingEnabled"), Boolean.valueOf(false)).booleanValue()); configuration.setAggressiveLazyLoading(booleanValueOf(props.getProperty("aggressiveLazyLoading"), Boolean.valueOf(true)).booleanValue()); configuration.setMultipleResultSetsEnabled(booleanValueOf(props.getProperty("multipleResultSetsEnabled"), Boolean.valueOf(true)).booleanValue()); configuration.setUseColumnLabel(booleanValueOf(props.getProperty("useColumnLabel"), Boolean.valueOf(true)).booleanValue()); configuration.setUseGeneratedKeys(booleanValueOf(props.getProperty("useGeneratedKeys"), Boolean.valueOf(false)).booleanValue()); configuration.setDefaultExecutorType(ExecutorType.valueOf(props.getProperty("defaultExecutorType", "SIMPLE"))); configuration.setDefaultStatementTimeout(integerValueOf(props.getProperty("defaultStatementTimeout"), null)); configuration.setMapUnderscoreToCamelCase(booleanValueOf(props.getProperty("mapUnderscoreToCamelCase"), Boolean.valueOf(false)).booleanValue()); configuration.setSafeRowBoundsEnabled(booleanValueOf(props.getProperty("safeRowBoundsEnabled"), Boolean.valueOf(false)).booleanValue()); //localCacheScope,一级缓存作用域 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.setDefaultScriptingLanguage(resolveClass(props.getProperty("defaultScriptingLanguage"))); configuration.setCallSettersOnNulls(booleanValueOf(props.getProperty("callSettersOnNulls"), Boolean.valueOf(false)).booleanValue()); configuration.setLogPrefix(props.getProperty("logPrefix")); configuration.setLogImpl(resolveClass(props.getProperty("logImpl"))); } }
//初始化environments
private void environmentsElement(XNode context) throws Exception { if(context != null) { if(environment == null) environment = context.getStringAttribute("default"); Iterator i$ = context.getChildren().iterator(); do { if(!i$.hasNext()) break; XNode child = (XNode)i$.next(); String id = child.getStringAttribute("id"); if(isSpecifiedEnvironment(id)) { TransactionFactory txFactory = transactionManagerElement(child.evalNode("transactionManager")); DataSourceFactory dsFactory = dataSourceElement(child.evalNode("dataSource")); javax.sql.DataSource dataSource = dsFactory.getDataSource(); org.apache.ibatis.mapping.Environment.Builder environmentBuilder = (new org.apache.ibatis.mapping.Environment.Builder(id)).transactionFactory(txFactory).dataSource(dataSource); configuration.setEnvironment(environmentBuilder.build()); } } while(true); } }
//Environment
public final class Environment { public static class Builder { public Builder transactionFactory(TransactionFactory transactionFactory) { this.transactionFactory = transactionFactory; return this; } public Builder dataSource(DataSource dataSource) { this.dataSource = dataSource; return this; } public String id() { return id; } public Environment build() { return new Environment(id, transactionFactory, dataSource); } private String id; private TransactionFactory transactionFactory; private DataSource dataSource; public Builder(String id) { this.id = id; } } private final String id; private final TransactionFactory transactionFactory; private final DataSource dataSource; }
初始化typeHandler
private void typeHandlerElement(XNode parent) throws Exception { if(parent != null) { for(Iterator i$ = parent.getChildren().iterator(); i$.hasNext();) { XNode child = (XNode)i$.next(); 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); } } } } }
//TypeHandlerRegistry
public final class TypeHandlerRegistry { public TypeHandlerRegistry() { //初始化java,变量,JDBCTYPE,及对应的Handler映射 register(java/lang/Boolean, new BooleanTypeHandler()); register(Boolean.TYPE, new BooleanTypeHandler()); register(JdbcType.BOOLEAN, new BooleanTypeHandler()); register(JdbcType.BIT, new BooleanTypeHandler()); register(java/lang/Byte, new ByteTypeHandler()); register(Byte.TYPE, new ByteTypeHandler()); register(JdbcType.TINYINT, new ByteTypeHandler()); register(java/lang/Short, new ShortTypeHandler()); register(Short.TYPE, new ShortTypeHandler()); register(JdbcType.SMALLINT, new ShortTypeHandler()); register(java/lang/Integer, new IntegerTypeHandler()); register(Integer.TYPE, new IntegerTypeHandler()); register(JdbcType.INTEGER, new IntegerTypeHandler()); register(java/lang/Long, new LongTypeHandler()); register(Long.TYPE, new LongTypeHandler()); register(java/lang/Float, new FloatTypeHandler()); register(Float.TYPE, new FloatTypeHandler()); register(JdbcType.FLOAT, new FloatTypeHandler()); register(java/lang/Double, new DoubleTypeHandler()); register(Double.TYPE, new DoubleTypeHandler()); register(JdbcType.DOUBLE, new DoubleTypeHandler()); register(java/lang/String, new StringTypeHandler()); register(java/lang/String, JdbcType.CHAR, new StringTypeHandler()); register(java/lang/String, JdbcType.CLOB, new ClobTypeHandler()); register(java/lang/String, JdbcType.VARCHAR, new StringTypeHandler()); register(java/lang/String, JdbcType.LONGVARCHAR, new ClobTypeHandler()); register(java/lang/String, JdbcType.NVARCHAR, new NStringTypeHandler()); register(java/lang/String, JdbcType.NCHAR, new NStringTypeHandler()); register(java/lang/String, JdbcType.NCLOB, new NClobTypeHandler()); register(JdbcType.CHAR, new StringTypeHandler()); register(JdbcType.VARCHAR, new StringTypeHandler()); register(JdbcType.CLOB, new ClobTypeHandler()); register(JdbcType.LONGVARCHAR, new ClobTypeHandler()); register(JdbcType.NVARCHAR, new NStringTypeHandler()); register(JdbcType.NCHAR, new NStringTypeHandler()); register(JdbcType.NCLOB, new NClobTypeHandler()); register(java/lang/Object, JdbcType.ARRAY, new ArrayTypeHandler()); register(JdbcType.ARRAY, new ArrayTypeHandler()); register(java/math/BigInteger, new BigIntegerTypeHandler()); register(JdbcType.BIGINT, new LongTypeHandler()); register(java/math/BigDecimal, new BigDecimalTypeHandler()); register(JdbcType.REAL, new BigDecimalTypeHandler()); register(JdbcType.DECIMAL, new BigDecimalTypeHandler()); register(JdbcType.NUMERIC, new BigDecimalTypeHandler()); register([Ljava/lang/Byte;, new ByteObjectArrayTypeHandler()); register([Ljava/lang/Byte;, JdbcType.BLOB, new BlobByteObjectArrayTypeHandler()); register([Ljava/lang/Byte;, JdbcType.LONGVARBINARY, new BlobByteObjectArrayTypeHandler()); register([B, new ByteArrayTypeHandler()); register([B, JdbcType.BLOB, new BlobTypeHandler()); register([B, JdbcType.LONGVARBINARY, new BlobTypeHandler()); register(JdbcType.LONGVARBINARY, new BlobTypeHandler()); register(JdbcType.BLOB, new BlobTypeHandler()); register(java/lang/Object, UNKNOWN_TYPE_HANDLER); register(java/lang/Object, JdbcType.OTHER, UNKNOWN_TYPE_HANDLER); register(JdbcType.OTHER, UNKNOWN_TYPE_HANDLER); register(java/util/Date, new DateTypeHandler()); register(java/util/Date, JdbcType.DATE, new DateOnlyTypeHandler()); register(java/util/Date, JdbcType.TIME, new TimeOnlyTypeHandler()); register(JdbcType.TIMESTAMP, new DateTypeHandler()); register(JdbcType.DATE, new DateOnlyTypeHandler()); register(JdbcType.TIME, new TimeOnlyTypeHandler()); register(java/sql/Date, new SqlDateTypeHandler()); register(java/sql/Time, new SqlTimeTypeHandler()); register(java/sql/Timestamp, new SqlTimestampTypeHandler()); register(java/lang/Character, new CharacterTypeHandler()); register(Character.TYPE, new CharacterTypeHandler()); } //注册jdbcType和TypeHandler的映射 public void register(JdbcType jdbcType, TypeHandler handler) { //JDBC_TYPE_HANDLER_MAP = new EnumMap(org/apache/ibatis/type/JdbcType); JDBC_TYPE_HANDLER_MAP.put(jdbcType, handler); } public void register(Class javaType, TypeHandler typeHandler) { register(((Type) (javaType)), typeHandler); } //注册javaType和TypeHandler的映射 private void register(Type javaType, TypeHandler typeHandler) { MappedJdbcTypes mappedJdbcTypes = (MappedJdbcTypes)typeHandler.getClass().getAnnotation(org/apache/ibatis/type/MappedJdbcTypes); if(mappedJdbcTypes != null) { JdbcType arr$[] = mappedJdbcTypes.value(); int len$ = arr$.length; for(int i$ = 0; i$ < len$; i$++) { JdbcType handledJdbcType = arr$[i$]; register(javaType, handledJdbcType, typeHandler); } if(mappedJdbcTypes.includeNullJdbcType()) register(javaType, null, typeHandler); } else { register(javaType, null, typeHandler); } } //注册javaTypeClass,jdbcType,typeHandlerClass的映射 public void register(Class javaTypeClass, JdbcType jdbcType, Class typeHandlerClass) { register(((Type) (javaTypeClass)), jdbcType, getInstance(javaTypeClass, typeHandlerClass)); } //获取TypeHandler,实例 public TypeHandler getInstance(Class javaTypeClass, Class typeHandlerClass) { if(javaTypeClass == null) break MISSING_BLOCK_LABEL_69; Constructor c = typeHandlerClass.getConstructor(new Class[] { java/lang/Class }); return (TypeHandler)c.newInstance(new Object[] { javaTypeClass }); } //注册javaTypeClass,jdbcType,typeHandlerClass的映射关系 private void register(Type javaType, JdbcType jdbcType, TypeHandler handler) { if(javaType != null) { Map map = (Map)TYPE_HANDLER_MAP.get(javaType); if(map == null) { map = new HashMap(); //TYPE_HANDLER_MAP,TYPE_HANDLER_MAP<javaType,Map<JdbcType,TypeHandler> TYPE_HANDLER_MAP.put(javaType, map); } map.put(jdbcType, handler); if(reversePrimitiveMap.containsKey(javaType)) register((Type)reversePrimitiveMap.get(javaType), jdbcType, handler); } ALL_TYPE_HANDLERS_MAP.put(handler.getClass(), handler); } private static final Map reversePrimitiveMap = new HashMap() { private static final long serialVersionUID = 1L; { put(java/lang/Byte, Byte.TYPE); put(java/lang/Short, Short.TYPE); put(java/lang/Integer, Integer.TYPE); put(java/lang/Long, Long.TYPE); put(java/lang/Float, Float.TYPE); put(java/lang/Double, Double.TYPE); put(java/lang/Boolean, Boolean.TYPE); put(java/lang/Character, Character.TYPE); } }; private final Map JDBC_TYPE_HANDLER_MAP = new EnumMap(org/apache/ibatis/type/JdbcType); private final Map TYPE_HANDLER_MAP = new HashMap(); private final TypeHandler UNKNOWN_TYPE_HANDLER = new UnknownTypeHandler(this); private final Map ALL_TYPE_HANDLERS_MAP = new HashMap(); }
//TypeHandler
public interface TypeHandler { public abstract void setParameter(PreparedStatement preparedstatement, int i, Object obj, JdbcType jdbctype) throws SQLException; public abstract Object getResult(ResultSet resultset, String s) throws SQLException; public abstract Object getResult(ResultSet resultset, int i) throws SQLException; public abstract Object getResult(CallableStatement callablestatement, int i) throws SQLException; }
//JdbcType
public final class JdbcType extends Enum { public static final JdbcType ARRAY; public static final JdbcType BIT; public static final JdbcType TINYINT; public static final JdbcType SMALLINT; public static final JdbcType INTEGER; public static final JdbcType BIGINT; public static final JdbcType FLOAT; public static final JdbcType REAL; public static final JdbcType DOUBLE; public static final JdbcType NUMERIC; public static final JdbcType DECIMAL; public static final JdbcType CHAR; public static final JdbcType VARCHAR; public static final JdbcType LONGVARCHAR; public static final JdbcType DATE; public static final JdbcType TIME; public static final JdbcType TIMESTAMP; public static final JdbcType BINARY; public static final JdbcType VARBINARY; public static final JdbcType LONGVARBINARY; public static final JdbcType NULL; public static final JdbcType OTHER; public static final JdbcType BLOB; public static final JdbcType CLOB; public static final JdbcType BOOLEAN; public static final JdbcType CURSOR; public static final JdbcType UNDEFINED; public static final JdbcType NVARCHAR; public static final JdbcType NCHAR; public static final JdbcType NCLOB; public static final JdbcType STRUCT; public final int TYPE_CODE; private static Map codeLookup; private static final JdbcType $VALUES[]; static { ARRAY = new JdbcType("ARRAY", 0, 2003); BIT = new JdbcType("BIT", 1, -7); TINYINT = new JdbcType("TINYINT", 2, -6); SMALLINT = new JdbcType("SMALLINT", 3, 5); INTEGER = new JdbcType("INTEGER", 4, 4); BIGINT = new JdbcType("BIGINT", 5, -5); FLOAT = new JdbcType("FLOAT", 6, 6); REAL = new JdbcType("REAL", 7, 7); DOUBLE = new JdbcType("DOUBLE", 8, 8); NUMERIC = new JdbcType("NUMERIC", 9, 2); DECIMAL = new JdbcType("DECIMAL", 10, 3); CHAR = new JdbcType("CHAR", 11, 1); VARCHAR = new JdbcType("VARCHAR", 12, 12); LONGVARCHAR = new JdbcType("LONGVARCHAR", 13, -1); DATE = new JdbcType("DATE", 14, 91); TIME = new JdbcType("TIME", 15, 92); TIMESTAMP = new JdbcType("TIMESTAMP", 16, 93); BINARY = new JdbcType("BINARY", 17, -2); VARBINARY = new JdbcType("VARBINARY", 18, -3); LONGVARBINARY = new JdbcType("LONGVARBINARY", 19, -4); NULL = new JdbcType("NULL", 20, 0); OTHER = new JdbcType("OTHER", 21, 1111); BLOB = new JdbcType("BLOB", 22, 2004); CLOB = new JdbcType("CLOB", 23, 2005); BOOLEAN = new JdbcType("BOOLEAN", 24, 16); CURSOR = new JdbcType("CURSOR", 25, -10); UNDEFINED = new JdbcType("UNDEFINED", 26, -2147482648); NVARCHAR = new JdbcType("NVARCHAR", 27, -9); NCHAR = new JdbcType("NCHAR", 28, -15); NCLOB = new JdbcType("NCLOB", 29, 2011); STRUCT = new JdbcType("STRUCT", 30, 2002); $VALUES = (new JdbcType[] { ARRAY, BIT, TINYINT, SMALLINT, INTEGER, BIGINT, FLOAT, REAL, DOUBLE, NUMERIC, DECIMAL, CHAR, VARCHAR, LONGVARCHAR, DATE, TIME, TIMESTAMP, BINARY, VARBINARY, LONGVARBINARY, NULL, OTHER, BLOB, CLOB, BOOLEAN, CURSOR, UNDEFINED, NVARCHAR, NCHAR, NCLOB, STRUCT }); codeLookup = new HashMap(); JdbcType arr$[] = values(); int len$ = arr$.length; for(int i$ = 0; i$ < len$; i$++) { JdbcType type = arr$[i$]; codeLookup.put(Integer.valueOf(type.TYPE_CODE), type); } } }
从上面可以看出;初始化typeHandler,就是初始化javaType,jdbcType,及TypeHandler的映射关系
初始化mappers
private void mapperElement(XNode parent) throws Exception { if(parent != null) { for(Iterator i$ = parent.getChildren().iterator(); i$.hasNext();) { XNode child = (XNode)i$.next(); 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); //加载Mapper的resource文件 InputStream inputStream = Resources.getResourceAsStream(resource); 构建XMLMapperBuilder 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); //mapperInterface信息添加到configuration configuration.addMapper(mapperInterface); } else { throw new BuilderException("A mapper element may only specify a url, resource or class, but not more than one."); } } } } }
回到SqlSessionFactoryBuilder,可以看到builder实际上是返回的是DefaultSqlSessionFactory
public SqlSessionFactory build(Configuration config) { return new DefaultSqlSessionFactory(config); }
总结:
从上,可以出SqlSessionFactoryBuilder做的主要工作是,加载全局配置文件,根据
properties,typeAliases,plugins,objectFactory,objectWrapperFactory
,settings,environments,databaseIdProvider,typeHandlers,mappers配置项,
初始化Configuration,由于mappers解析内容较多,我们放在下一篇来讲。
附:Mapper解析的引篇
//Configuration
public void addMapper(Class type) { mapperRegistry.addMapper(type); }
//MapperRegistry
public class MapperRegistry { public void addMapper(Class type) { boolean loadCompleted; if(!type.isInterface()) break MISSING_BLOCK_LABEL_125; if(hasMapper(type)) throw new BindingException((new StringBuilder()).append("Type ").append(type).append(" is already known to the MapperRegistry.").toString()); loadCompleted = false; knownMappers.put(type, new MapperProxyFactory(type)); MapperAnnotationBuilder parser = new MapperAnnotationBuilder(config, type); parser.parse(); loadCompleted = true; if(!loadCompleted) knownMappers.remove(type); break MISSING_BLOCK_LABEL_125; Exception exception; exception; if(!loadCompleted) knownMappers.remove(type); throw exception; } private Configuration config; //HashMap<Class,MapperProxyFactory> private final Map knownMappers = new HashMap(); }
//MapperProxyFactory
public class MapperProxyFactory { public MapperProxyFactory(Class mapperInterface) { methodCache = new ConcurrentHashMap(); this.mapperInterface = mapperInterface; } protected Object newInstance(MapperProxy mapperProxy) { //代理生成实例 return Proxy.newProxyInstance(mapperInterface.getClassLoader(), new Class[] { mapperInterface }, mapperProxy); } public Object newInstance(SqlSession sqlSession) { MapperProxy mapperProxy = new MapperProxy(sqlSession, mapperInterface, methodCache); return newInstance(mapperProxy); } private final Class mapperInterface; private Map methodCache; }
//MapperProxy
public class MapperProxy implements InvocationHandler, Serializable { public MapperProxy(SqlSession sqlSession, Class mapperInterface, Map methodCache) { this.sqlSession = sqlSession; this.mapperInterface = mapperInterface; this.methodCache = methodCache; } public Object invoke(Object proxy, Method method, Object args[]) throws Throwable { if(java/lang/Object.equals(method.getDeclaringClass())) { return method.invoke(this, args); } else { MapperMethod mapperMethod = cachedMapperMethod(method); return mapperMethod.execute(sqlSession, args); } } private MapperMethod cachedMapperMethod(Method method) { MapperMethod mapperMethod = (MapperMethod)methodCache.get(method); if(mapperMethod == null) { mapperMethod = new MapperMethod(mapperInterface, method, sqlSession.getConfiguration()); methodCache.put(method, mapperMethod); } return mapperMethod; } private static final long serialVersionUID = -6424540398559729838L; private final SqlSession sqlSession; private final Class mapperInterface; //Map<Method,MapperMethod>,即二级缓存 private final Map methodCache; }
从上可以看出Configuration添加MapperInterface,就是MapperRegistry注册到其
HashMap<Class,MapperProxyFactory>中,MapperProxyFactory是MapperInterface的代理,
生成MapperInterface的MapperProxy代理实例,MapperProxy中利用Map<Method,MapperMethod>,
实现二级缓存
//MapperAnnotationBuilder,MapperInterface的注解处理
public class MapperAnnotationBuilder { public MapperAnnotationBuilder(Configuration configuration, Class type) { String resource = (new StringBuilder()).append(type.getName().replace('.', '/')).append(".java (best guess)").toString(); assistant = new MapperBuilderAssistant(configuration, resource); this.configuration = configuration; this.type = type; sqlAnnotationTypes.add(org/apache/ibatis/annotations/Select); sqlAnnotationTypes.add(org/apache/ibatis/annotations/Insert); sqlAnnotationTypes.add(org/apache/ibatis/annotations/Update); sqlAnnotationTypes.add(org/apache/ibatis/annotations/Delete); sqlProviderAnnotationTypes.add(org/apache/ibatis/annotations/SelectProvider); sqlProviderAnnotationTypes.add(org/apache/ibatis/annotations/InsertProvider); sqlProviderAnnotationTypes.add(org/apache/ibatis/annotations/UpdateProvider); sqlProviderAnnotationTypes.add(org/apache/ibatis/annotations/DeleteProvider); } //解析CacheNamespace注解 private void parseCache() { CacheNamespace cacheDomain = (CacheNamespace)type.getAnnotation(org/apache/ibatis/annotations/CacheNamespace); if(cacheDomain != null) assistant.useNewCache(cacheDomain.implementation(), cacheDomain.eviction(), Long.valueOf(cacheDomain.flushInterval()), Integer.valueOf(cacheDomain.size()), cacheDomain.readWrite(), null); } //解析CacheNamespaceRef注解 private void parseCacheRef() { CacheNamespaceRef cacheDomainRef = (CacheNamespaceRef)type.getAnnotation(org/apache/ibatis/annotations/CacheNamespaceRef); if(cacheDomainRef != null) assistant.useCacheRef(cacheDomainRef.value().getName()); } private String parseResultMap(Method method) { Class returnType = getReturnType(method); ConstructorArgs args = (ConstructorArgs)method.getAnnotation(org/apache/ibatis/annotations/ConstructorArgs); Results results = (Results)method.getAnnotation(org/apache/ibatis/annotations/Results); TypeDiscriminator typeDiscriminator = (TypeDiscriminator)method.getAnnotation(org/apache/ibatis/annotations/TypeDiscriminator); String resultMapId = generateResultMapName(method); applyResultMap(resultMapId, returnType, argsIf(args), resultsIf(results), typeDiscriminator); return resultMapId; } //处理Statement方法method void parseStatement(Method method) {} private final Set sqlAnnotationTypes = new HashSet(); private final Set sqlProviderAnnotationTypes = new HashSet(); private Configuration configuration; private MapperBuilderAssistant assistant; private Class type; }
发表评论
-
Mybatis缓存实现
2016-12-07 10:36 983SqlSessionFactory初始化:http://don ... -
DefaultSqlSession第三讲-事务提交,回滚,关闭SqlSession,清除缓存
2016-11-20 11:07 5714上面两篇讲过query和update及flushStateme ... -
DefaultSqlSession第二讲-更新,刷新Statement
2016-11-20 11:06 635上一篇文章中,我们讲到DefaultSqlSession的查询 ... -
DefaultSqlSession第一讲query解析
2016-11-20 11:06 1631上一篇文章:我们说过DefaultSqlSession,Def ... -
Mybatis的SqlSession解析
2016-11-20 11:02 2566在前文中,Mybatis使用教程中,有下面一段代码: Sql ... -
Mybatis的Reflector解析
2016-11-18 12:53 2165Mybatis的MetaObject解析:http://don ... -
Mybatis的MetaObject解析
2016-11-18 11:40 9585SqlSessionFactory初始化:http://don ... -
mybatis 动态标签语句的解析(BoundSql)
2016-10-30 09:48 5767SqlSessionFactory初始化:http://don ... -
Mybatis的Environment解析详解
2016-10-29 18:28 1998SqlSessionFactory初始化:http://don ... -
Mybatis 解析Mapper(class)
2016-10-26 11:44 3365SqlSessionFactory初始化:http://don ... -
Mybatis加载解析Mapper(xml)文件第二讲
2016-10-25 21:30 4806SqlSessionFactory初始化:http://don ... -
Mybatis加载解析Mapper(xml)文件第一讲
2016-10-25 16:51 6201SqlSessionFactory初始化:http://don ... -
mybatis 使用教程
2016-10-14 09:03 914Myeclispe下mybatis generator的使 ... -
Spring+Mybatis多数据源的实现
2016-09-21 18:15 3096浅谈Spring事务隔离级别:http://www.cnblo ... -
mybaitis CDATA 防止字符被解析
2016-08-17 18:45 727在使用mybatis 时我们sql是写在xml 映射文件中,如 ... -
Myeclispe下mybatis generator的使用
2016-07-05 18:05 1379准备:下载附件包解压到myeclispe的dropins文件夹 ...
相关推荐
2. **SQLSessionFactory初始化**(73.尚硅谷_MyBatis_运行原理_SQLSessionFactory的初始化.avi):SQLSessionFactory是Mybatis的核心对象,负责创建SqlSession实例。视频会详细解析配置文件、XML映射文件的加载过程...
MyBatis的初始化主要涉及加载配置信息,创建`Configuration`对象,以及构建`SqlSessionFactory`。 首先,让我们详细探讨MyBatis的初始化做了什么。在启动过程中,MyBatis会加载配置文件,这个配置文件通常是一个名...
Spring MVC提供了强大的功能,如声明式事务管理、数据验证、国际化支持等,使得开发者可以更专注于业务逻辑,而非底层实现。 3. **Spring Boot框架**: Spring Boot是由Pivotal Team提供的一个开源框架,旨在简化...
这个"ssm项目 初始化资源,父子依赖项目"标题表明这是一个关于使用SSM框架初始化一个新的项目,并涉及到项目的父子依赖结构。 在Java Web开发中,Spring作为一个全功能的容器,负责管理应用中的对象(bean),提供...
6. **初始化SqlSessionFactory**:在应用启动时,使用`SqlSessionFactoryBuilder`创建`SqlSessionFactory`,这是Mybatis的主要入口点: ```java SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder...
2. **延迟初始化与依赖注入**:使用`sqlSessionFactoryBeanName`的一个关键好处是它可以避免在`MapperScannerConfigurer`启动时过早初始化`SqlSessionFactory`。因为在Spring容器启动的早期阶段,配置文件中的占位符...
MyBatis 初始化的核心任务是创建 `SqlSessionFactory` 对象。`SqlSessionFactory` 是用来创建 `SqlSession` 的工厂,而 `SqlSession` 提供了在数据库执行 SQL 命令所需的所有方法。 ##### 2.1 获取配置文件 - **...
Maven使用约定优于配置的原则,这意味着它有一套默认的构建生命周期和构建目录结构,简化了项目的初始化和维护。 二、Maven Web项目结构 一个典型的Maven Web项目结构如下: 1. pom.xml:项目对象模型文件,包含...
在MyBatis中,SqlSessionFactory和SqlSession是核心组件,前者用于创建SqlSession对象,后者则负责执行SQL操作。MyBatis的Mapper接口和Mapper XML文件则是业务逻辑与SQL语句之间的桥梁。 Spring是一个全面的后端...
1. 实例化:MyBatis在初始化阶段会创建一个名为SqlSessionFactory的工厂对象,它是整个MyBatis应用的核心。SqlSessionFactory是线程安全的,其作用是创建SqlSession实例。通常情况下,一个SqlSessionFactory只需要...
- **饿汉模式**:SqlSessionFactory在类加载时就创建,提前初始化,确保线程安全,但牺牲了资源的按需加载。 ```java public class EagerMyBatisConfig { private static final SqlSessionFactory ...
同时,我们可以利用Spring的AOP(面向切面编程)来插入自定义逻辑,或者通过@Bean注解来定制初始化过程。 例如,我们可以创建一个新的`ExtendedSqlSessionFactoryBean`类,继承自`SqlSessionFactoryBean`,并添加新...
在初始化阶段,提供初始化方法,InitializingBean接口,实现afterPropertiesSet方法初始化。在销毁阶段,提供销毁方法,DisposableBean接口,实现destroy方法销毁。 八、配置文件参数化 Spring提供了多种方法来...
在实际应用中,我们需要先初始化SqlSessionFactory,然后通过SqlSessionFactory创建SqlSession实例,接着通过SqlSession调用Mapper接口的方法: ```java SqlSessionFactory sqlSessionFactory = ...; // 初始化...
SpringBoot的特点在于“开箱即用”,提供了许多默认配置,极大地减少了项目初始化和配置的工作量。核心组件包括SpringApplication、自动配置、起步依赖和Actuator。 SpringApplication是SpringBoot程序的入口,负责...
2. 创建会话模板 SqlSessionTemplate:MapperFactoryBean 在初始化时,会调用 SqlSessionDaoSupport 的 setSqlSessionFactory 方法,进一步创建 SqlSessionTemplate 实例。 3. 获取 Mapper 对象:当通过 Bean ID ...
功能描述: 配置MyBatis和数据源,包括SqlSessionFactory和事务管理器的初始化。 2. 应用启动类 文件路径: srcmainjavacomtuqiTuqiAllApplication.java 功能描述: Spring Boot应用的入口类,负责启动应用上下文...
初始化涉及XMLConfigBuilder中的pluginElement解析,加载时会在Configuration创建四大对象(Executor、SqlSessionTemplate、SqlSessionFactory、MapperRegistry)的过程中应用插件。最后,插件的调用主要通过Plugin...
在SSM项目中,数据库初始化是非常重要的一步,因为我们的业务逻辑和数据模型都需要依赖于这些预先定义的数据库结构。当项目启动时,尤其是进行本地开发或部署新环境时,运行这些SQL脚本可以帮助我们快速搭建起与项目...
这段代码展示了如何初始化SqlSessionFactory,并提供了一个静态方法`getSqlSession()`,方便在应用中获取SqlSession实例。 总的来说,Mybatis提供了一种灵活的方式来进行数据库操作,通过XML或注解配置,将SQL语句...