首页 > 代码库 > 希望有兴趣的加入,共同为项目智能化管理jar包而努力 第二篇

希望有兴趣的加入,共同为项目智能化管理jar包而努力 第二篇

 
想听听大家对于我这个想法的一些看法,喷也好,赞也罢,希望留下您宝贵的建议!
 

有共同想法并且想实现的请入群 2500261120 

 
在使用autort插件时,首先要到autort服务器下载所有的jar包快照。里面存在了检索jar的相关信息。
 
在第一篇我们专门介绍过如何划分java类中出现的某一串字符,想了解的或者不知道我要干什么的请点这里 。其实说白了,也就是系统的整个类的组织及查询方式。Trie树可以在我们知道类全名的情况下尽快找到所需要的类。
 
当通过类全名找到存储某个类的Node时,此Node中有个map属性,key为类名,而值保存了这个类在版本迭代过程中的所有快照。类似于Git用快照来保存文件迭代的过程。不同的是,这里的快照是类的快照,而不是文件。类似如下形式:
 
一个类的不同快照会使用List列表来存储,因为版本的迭代发布本来就是有先后顺序的。快照的具体json结构如下:
 
{
   serialVersion:快照支持的一系列版本,这些版本都是连续的
   type:{
   modifiers:修饰符
   type:表示类型,如1代表类,2代表interface,3代表枚举,4为注解定义
   name:内部类的写法为outer.innter  
   extends:全类名的形式
   implements:[] 多个类全名的形式
   types:[] 存储多个type 
   fields:1[
       {
        modifiers:方法修饰符
        declType:方法返回类型,也是全类名的形式
        name:方法名称
       }
       ...
   ]
   methods:[
       {
         modifiers:方法修饰符 
         returnType:方法返回类型,也是全类名的形式
         name:方法名称
         throws:全类名的形式
         arguments:[] 多个全类名的形式
       }
       ...
   ]  
    }
} 

 

首先介绍一下serialVersion属性。
 
举个例子,spring-core从开始发布版本至今共有90个版本。假如某个类A在1.2.8版本之前一直没有变化,那么这个serialVersion代表着之前的所有版本(共25个)。
 
假如在2.0进行API调整或者类重构时,这个类发生了变化,也就是快照中保存的某个或者多个属性发生了变化,比如某个方法的参数类型改变了,那么需要再生成一个快照结构,代表这次的变化。假如这次重构后经历了10次版本迭代仍然没有变化,那么这个结构中的serialVersion标识这10个版本。
 
如果下一次重构时,这个类变换了类路径,那么它将做为相应类路径下一个新建的类开始存在。而原来的快照只保存之前的35个版本快照。
 
下面重点来看一下type属性。
 
modifiers修饰符的定义:
 
技术分享
 
例如某个类的修饰符有public和final,那么modifiers的值为 PUBLIC|FINAL
 
extends为字符串形式,存储了这个类可能继承的其它类。如果为空,默认为Object
 
implements类型为数组,存储值必须为全名,以方便通过Trie树迅速查找到这些接口相关的信息。可以为空。
 
types属性。这个属性中存储了多个type结构,这个type结构可能是类(包括抽象类)、接口、枚举类和注解定义类。
 
无论这个内部的结构有什么修饰符都需要存储相关的信息。和我们后面将要提到的属性与方法略有不同,属性与方法是通过不同的修饰符选择性存储。
 
举个例子:
 
public class Father01 {
	private class A{
		public int a = 2;
	}
	public class B extends A{
		
	}
}
类A虽然是private,但是B继承了A。客户端的代码如下:
 
public class Son01 extends Father01{
	public void test(){
	    B b = new B();
	    int x=b.a; // 使用了嵌套类A中声明的属性
	}
}
但是在块内Block定义的类就不需要保存了,因为封闭性较好,通常情况下无法被外部使用。接口,枚举类与注解定义类不能在块内定义。
 
 
剩下就是fields与methods了,目前private与默认访问控制符修饰的变量与方法不建立快照相关信息。
 
如果程序通过反射操作了三方包中的一些类属性,那么快照中需要存储所有的方法(包括构造方法)与变量,因为反射可以获取到类所有相关的信息。这会使快照的数据量变大并且快照数量变多,目前暂不考虑。
 
下面来说一说方法中的throws异常吧。
 
修改了某个公有方法抛出的异常。由原来的某个不受检查异常变为了受检查的异常,那么这一版本jar包就已经不满足我们程序的要求了,autort会通过检测将这一版本排除在可选择范围之外。
 
需要说明的是,并不是修改了方法抛出的异常就会为type新建快照,但是从某个检查异常修改为另外的检查异常,即使两者之间有继承关系,也一定会建立新的快照。不会对Error与RuntimeException的异常进行信息保存与处理,因为这些异常不会让现有的一些程序出错。
 
如下实例:
 
 
public void test() throws ReflectiveOperationException,NullPointerException{  ...   }
public void testException(){
   try {
        test();
   }catch (ReflectiveOperationException e) {
        e.printStackTrace();
   }
}
 
test方法新增加了一个非检查异常NullPointerException并且在testException方法中调用了这个方法,但是并不需要修改相关调用的代码。
 
 
其实我只说了需要存储哪些信息,并没有说为什么要选择性存储这些信息,我们可以思考一个问题:我们的程序使用了第三方jar包提供的相关功能,一搬情况下也就是下面几种:
 
(1)调用一个方法,使用new关键字创建对象时也看作调用它的构造方法,返回类型为构造方法所在的类类型。
(2)调用一个变量
(3)继承了三方的类或者实现了三方定义的接口
 
快照中需要存储足够的信息,当客户通过如上一种或多种方式使用了jar包功能时,可以通过扫描分析这些代码并结合快照中jar包类迭代的信息,快速找到当前代码合适的版本。
 
 
最终一个整体的存储结构大概如下图所示。

技术分享

 

需要说明的是,一个jar包就需要有这样的一个结构来组织和存储相关的信息,主要是考虑到不同jar包会有类全名(包路径和类名)相等的情况,更重要的是会通过这样的结构来选择性加载到内存。
 

  

  

  

 

 

 

希望有兴趣的加入,共同为项目智能化管理jar包而努力 第二篇