SqlSessionFactory初始化

mybatis 使用教程:[url]http://donald-draper.iteye.com/blog/2330429[/url]
Mybatis加载解析Mapper(xml)文件第一讲:[url]http://donald-draper.iteye.com/blog/2333125[/url]
Mybatis加载解析Mapper(xml)文件第二讲:[url]http://donald-draper.iteye.com/blog/2333191[/url]
在使用教程,我们有一个静态方法,初始化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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值