在mybatis中我们经常配置,别名来简化我们的配置文件书写,其中配置别名的方式我们常用的一个是直接配置,另一个是配置package来让mybatis进行扫描。
我们来看一下mybatis对这个标签的解析代码。在mybatis的XMLConfigBuilder类中的parseConfiguration方法,集合了对各种配置属性的解析,其中有一句
this.typeAliasesElement(root.evalNode("typeAliases"));
就是对typeAliases的解析,我们来看一下具体方法
private void typeAliasesElement(XNode parent) {
if (parent != null) {
Iterator i$ = parent.getChildren().iterator();
while(i$.hasNext()) {
XNode child = (XNode)i$.next();
String alias;
if ("package".equals(child.getName())) {
alias = child.getStringAttribute("name");
this.configuration.getTypeAliasRegistry().registerAliases(alias);
} else {
alias = child.getStringAttribute("alias");
String type = child.getStringAttribute("type");
try {
Class> clazz = Resources.classForName(type);
if (alias == null) {
this.typeAliasRegistry.registerAlias(clazz);
} else {
this.typeAliasRegistry.registerAlias(alias, clazz);
}
} catch (ClassNotFoundException var7) {
throw new BuilderException("Error registering typeAlias for '" + alias + "'. Cause: " + var7, var7);
}
}
}
}
}
其实我们在刚进去
typeAliasesElement
方法的时候就发现XMLConfigBuilder的typeAliasRegistry属性中就已经有一些值了,其实这些值是系统为我们定义的别名,这些别名是在哪儿初始化的呢?
我们知道,在调用SqlSessionFactoryBuilder的build构造SqlSessionFactory的时候,在解析配置文件的时候,有调用XMLConfigBuilder的构造方法
public SqlSessionFactory build(InputStream inputStream, String environment, Properties properties) {
SqlSessionFactory var5;
try {
XMLConfigBuilder parser = new XMLConfigBuilder(inputStream, environment, properties);
var5 = this.build(parser.parse());
} catch (Exception var14) {
throw ExceptionFactory.wrapException("Error building SqlSession.", var14);
} finally {
ErrorContext.instance().reset();
try {
inputStream.close();
} catch (IOException var13) {
;
}
}
return var5;
}
这些系统定义的别名就是在这个构造方法中初始化的,我们进去看看
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;
}
看这个构造函数的第一行代码super(new Configuraction)先看Configuration的构造
public Configuration() {
this.safeRowBoundsEnabled = false;
this.safeResultHandlerEnabled = true;
this.mapUnderscoreToCamelCase = false;
this.aggressiveLazyLoading = true;
this.multipleResultSetsEnabled = true;
this.useGeneratedKeys = false;
this.useColumnLabel = true;
this.cacheEnabled = true;
this.callSettersOnNulls = false;
this.localCacheScope = LocalCacheScope.SESSION;
this.jdbcTypeForNull = JdbcType.OTHER;
this.lazyLoadTriggerMethods = new HashSet(Arrays.asList("equals", "clone", "hashCode", "toString"));
this.defaultExecutorType = ExecutorType.SIMPLE;
this.autoMappingBehavior = AutoMappingBehavior.PARTIAL;
this.variables = new Properties();
this.objectFactory = new DefaultObjectFactory();
this.objectWrapperFactory = new DefaultObjectWrapperFactory();
this.mapperRegistry = new MapperRegistry(this);
this.lazyLoadingEnabled = false;
this.interceptorChain = new InterceptorChain();
this.typeHandlerRegistry = new TypeHandlerRegistry();
this.typeAliasRegistry = new TypeAliasRegistry();
this.languageRegistry = new LanguageDriverRegistry();
this.mappedStatements = new Configuration.StrictMap("Mapped Statements collection");
this.caches = new Configuration.StrictMap("Caches collection");
this.resultMaps = new Configuration.StrictMap("Result Maps collection");
this.parameterMaps = new Configuration.StrictMap("Parameter Maps collection");
this.keyGenerators = new Configuration.StrictMap("Key Generators collection");
this.loadedResources = new HashSet();
this.sqlFragments = new Configuration.StrictMap("XML fragments parsed from previous mappers");
this.incompleteStatements = new LinkedList();
this.incompleteCacheRefs = new LinkedList();
this.incompleteResultMaps = new LinkedList();
this.incompleteMethods = new LinkedList();
this.cacheRefMap = new HashMap();
this.typeAliasRegistry.registerAlias("JDBC", JdbcTransactionFactory.class);
this.typeAliasRegistry.registerAlias("MANAGED", ManagedTransactionFactory.class);
this.typeAliasRegistry.registerAlias("JNDI", JndiDataSourceFactory.class);
this.typeAliasRegistry.registerAlias("POOLED", PooledDataSourceFactory.class);
this.typeAliasRegistry.registerAlias("UNPOOLED", UnpooledDataSourceFactory.class);
this.typeAliasRegistry.registerAlias("PERPETUAL", PerpetualCache.class);
this.typeAliasRegistry.registerAlias("FIFO", FifoCache.class);
this.typeAliasRegistry.registerAlias("LRU", LruCache.class);
this.typeAliasRegistry.registerAlias("SOFT", SoftCache.class);
this.typeAliasRegistry.registerAlias("WEAK", WeakCache.class);
this.typeAliasRegistry.registerAlias("DB_VENDOR", VendorDatabaseIdProvider.class);
this.typeAliasRegistry.registerAlias("XML", XMLLanguageDriver.class);
this.typeAliasRegistry.registerAlias("RAW", RawLanguageDriver.class);
this.typeAliasRegistry.registerAlias("SLF4J", Slf4jImpl.class);
this.typeAliasRegistry.registerAlias("COMMONS_LOGGING", JakartaCommonsLoggingImpl.class);
this.typeAliasRegistry.registerAlias("LOG4J", Log4jImpl.class);
this.typeAliasRegistry.registerAlias("LOG4J2", Log4j2Impl.class);
this.typeAliasRegistry.registerAlias("JDK_LOGGING", Jdk14LoggingImpl.class);
this.typeAliasRegistry.registerAlias("STDOUT_LOGGING", StdOutImpl.class);
this.typeAliasRegistry.registerAlias("NO_LOGGING", NoLoggingImpl.class);
this.typeAliasRegistry.registerAlias("CGLIB", CglibProxyFactory.class);
this.typeAliasRegistry.registerAlias("JAVASSIST", JavassistProxyFactory.class);
this.languageRegistry.setDefaultDriverClass(XMLLanguageDriver.class);
this.languageRegistry.register(RawLanguageDriver.class);
}
其中有调用TypeAliasRegistry的构造方法,其中这个构造方法就初始化了一部分系统定义的别名
public TypeAliasRegistry() {
this.registerAlias("string", String.class);
this.registerAlias("byte", Byte.class);
this.registerAlias("long", Long.class);
this.registerAlias("short", Short.class);
this.registerAlias("int", Integer.class);
this.registerAlias("integer", Integer.class);
this.registerAlias("double", Double.class);
this.registerAlias("float", Float.class);
this.registerAlias("boolean", Boolean.class);
this.registerAlias("byte[]", Byte[].class);
this.registerAlias("long[]", Long[].class);
this.registerAlias("short[]", Short[].class);
this.registerAlias("int[]", Integer[].class);
this.registerAlias("integer[]", Integer[].class);
this.registerAlias("double[]", Double[].class);
this.registerAlias("float[]", Float[].class);
this.registerAlias("boolean[]", Boolean[].class);
this.registerAlias("_byte", Byte.TYPE);
this.registerAlias("_long", Long.TYPE);
this.registerAlias("_short", Short.TYPE);
this.registerAlias("_int", Integer.TYPE);
this.registerAlias("_integer", Integer.TYPE);
this.registerAlias("_double", Double.TYPE);
this.registerAlias("_float", Float.TYPE);
this.registerAlias("_boolean", Boolean.TYPE);
this.registerAlias("_byte[]", byte[].class);
this.registerAlias("_long[]", long[].class);
this.registerAlias("_short[]", short[].class);
this.registerAlias("_int[]", int[].class);
this.registerAlias("_integer[]", int[].class);
this.registerAlias("_double[]", double[].class);
this.registerAlias("_float[]", float[].class);
this.registerAlias("_boolean[]", boolean[].class);
this.registerAlias("date", Date.class);
this.registerAlias("decimal", BigDecimal.class);
this.registerAlias("bigdecimal", BigDecimal.class);
this.registerAlias("biginteger", BigInteger.class);
this.registerAlias("object", Object.class);
this.registerAlias("date[]", Date[].class);
this.registerAlias("decimal[]", BigDecimal[].class);
this.registerAlias("bigdecimal[]", BigDecimal[].class);
this.registerAlias("biginteger[]", BigInteger[].class);
this.registerAlias("object[]", Object[].class);
this.registerAlias("map", Map.class);
this.registerAlias("hashmap", HashMap.class);
this.registerAlias("list", List.class);
this.registerAlias("arraylist", ArrayList.class);
this.registerAlias("collection", Collection.class);
this.registerAlias("iterator", Iterator.class);
this.registerAlias("ResultSet", ResultSet.class);
}
然后另一部分就是在Configuration的构造方法中注册的。
然后回到我们XMLConfigBuilder的构造方法,看其中的super(newConfiguration())看其调用父类的构造方法来初始化一些值。
public BaseBuilder(Configuration configuration) {
this.configuration = configuration;
this.typeAliasRegistry = this.configuration.getTypeAliasRegistry();
this.typeHandlerRegistry = this.configuration.getTypeHandlerRegistry();
}
其中就把configuration中已经注册的别名赋值给了其typeAliasRegistry属性。
至此我们已经知道系统定义的别名来源。现在我们回到用户自定义别名的解析。继续看我们的XMLConfigBuilder的typeAliasesElement方法。
我配置文件中配置了
这个解析会按照顺序来解析
解析配置的看结果
解析package看结果
其中com.cyy.mybatis.alias包的内容如下
其中AAA类采用了Alias注解来指定别名,AbAbA没用采用注解,别名系统自动生成。
我们看到如果我们用注解指定指定别名,扫描注册的别名就是我们指定的,如果没有指定,就是系统自动生成的,生成规则就是简单类名的小写。
至此别名配置解析完成。