然后可以看到注册所有别名的方法 ,registerAliases是怎么做的?
configuration.getTypeAliasRegistry().registerAliases(packageToScan, typeAliasesSuperType == null ? Object.class : typeAliasesSuperType);要扫描注册所有的别名之前先要扫描包下面的所有类:
public void registerAliases(String packageName, Class<?> superType) { ResolverUtil<Class<?>> resolverUtil = new ResolverUtil(); resolverUtil.find(new IsA(superType), packageName); //通过ResolverUtil获取到的所有类都赋值给一个集合 Set<Class<? extends Class<?>>> typeSet = resolverUtil.getClasses(); /*遍历集合,然后一个个注册*/ Iterator var5 = typeSet.iterator(); while(var5.hasNext()) { Class<?> type = (Class)var5.next(); if (!type.isAnonymousClass() && !type.isInterface() && !type.isMemberClass()) { this.registerAlias(type); } } }ResolverUtil是怎么通过packageName去查找的呢,可以再继续跟一下
public ResolverUtil<T> find(ResolverUtil.Test test, String packageName) { //获取包路径 String path = this.getPackagePath(packageName); try { //VFS类用单例模式实现,先获取集合 List<String> children = VFS.getInstance().list(path); Iterator var5 = children.iterator(); //遍历,.class文件的选出来 while(var5.hasNext()) { String child = (String)var5.next(); if (child.endsWith(".class")) { this.addIfMatching(test, child); } } } catch (IOException var7) { log.error("Could not read package: " + packageName, var7); } return this; }获取packPath只是获取一下相对路径
protected String getPackagePath(String packageName) { return packageName == null ? null : packageName.replace('.', 'http://www.likecs.com/'); }校验方法addIfMatching:
protected void addIfMatching(ResolverUtil.Test test, String fqn) { try { String externalName = fqn.substring(0, fqn.indexOf(46)).replace('http://www.likecs.com/', '.'); ClassLoader loader = this.getClassLoader();//类加载器 if (log.isDebugEnabled()) { log.debug("Checking to see if class " + externalName + " matches criteria [" + test + "]"); } Class<?> type = loader.loadClass(externalName);//通过类加载器加载类 if (test.matches(type)) {//校验是否符合 this.matches.add(type); } } catch (Throwable var6) { log.warn("Could not examine class '" + fqn + "' due to a " + var6.getClass().getName() + " with message: " + var6.getMessage()); } }VFS类具体是怎么setInstance的?继续跟:
//这里的关键点就是getResources,Thread.currentThread().getContextClassLoader().getResources(),其实总结一下Mybatis的类扫描还是要依赖与jdk提供的类加载器 protected static List<URL> getResources(String path) throws IOException { //获取到资源路径以列表形式放在集合里 return Collections.list(Thread.currentThread().getContextClassLoader().getResources(path)); } ... public List<String> list(String path) throws IOException { List<String> names = new ArrayList(); Iterator var3 = getResources(path).iterator(); //遍历封装成列表 while(var3.hasNext()) { URL url = (URL)var3.next(); names.addAll(this.list(url, path)); } return names; }ok,本博客只是稍微跟一下源码,并没有对Mybatis的源码进行比较系统更高层次的分析。
跟了一下源码知道,稍微总结一下Mybatis对别名的注册是先将从sqlSessionFactoryBean类set的别名报名进行tokenizeToStringArray拆分成数组,然后将包名数组丢给ResolverUtil类和VFS等类进行一系列类加载遍历,之后将 resolverUtil.getClasses()获取的类都赋值给Set<Class<? extends Class<?>>> typeSet 一个集合。其中也是依赖与类加载器。