• SpringBoot探索02 – 启动过程之getSpringFactoriesInstances

    最近计划整理下SpringBoot的启动过程以及API请求返回过程,以便支持后续的部分内容,也方便实现一周一文的计划。 先做SpringBoot启动流程分析。 初见 在SpringBoot启动代码的开头部分可以看到如下的内容: 比较显眼的是getSpringFactoriesInstances方法——这个方法出现了两次,而且以后还会继续出现。 从代码上看来,这个方法的作用应该就是获取指定类型的实例集合。 具体如何,还得继续走走看。从这里一步步走下去,可以看到一个重载的方法,这个方法的内容比较实在: 关键是方法体中的三四两行。第三行应该是获取了名称集合,第四行则应是获取了名称对应的实例集合。 问名 首先看看SpringFactoriesLoader.loadFactoryNames方法做了哪些事情。这个方法的核心内容在于它调用的loadSpringFactories方法。loadSpringFactories的方法体稍稍长了一些,沾出来显得太啰嗦,所以仅在下面介绍下这个方法具体做了那些事情。 这个类的作用是根据类加载器获取类名称集合(map结构,接口->实现类集合),具体流程如下: 首先尝试从内存缓存中获取,如获取到就立即返回,没有则继续下面内容; 从类加载路径(的jar文件)中获取全部的spring.factories文件路径; 循环遍历读取这些文件中的键值对(K->List[V]); 将读取内容放入内存缓存,下次再调用这个方法时会优先从缓存中获取; 返回读取到的全部键值对集合(Map[K,List[V]]结构)。 简单做些解释: spring.factories文件本质上是一个.properties文件,也就是说,它的内容是键值对集合,下面是一段示例: 这个片段中有三个键值对。根据后面的代码可知spring.factories文件中每个键值对的key是一个接口的名称,value则是实现类名称的集合(以“,”分隔)。 spring.factories文件中的内容会被读取到一个(K->List[V])结构的Map中。最终全部这些内容又会以类加载器实例为key保存在内存缓存中。 然后,SpringFactoriesLoader.loadFactoryNames方法就可以根据接口的名称获取到接口的实现类的名称集合了。 得意 在得到类名称集合后就是根据类名构建类对应的实例了。这是createSpringFactoriesInstances方法做的事情。这个方法不长,可以粘出来看看: 方法的内容很清晰也很简单: 根据方法名获取Class实例; 通过Class实例获取构造器; 使用构造器构建类实例。 很普通的一个反射过程。期间有一个校验是判断Class是不是指定接口的子类;还有就是在BeanUtils.instantiateClass中创建实例的时候修改了构造器的可见性范围,并提供了对Kotlin的支持。 这块儿内容大体上就这样了。至于这里获取到了哪些ApplicationContextInitializer和ApplicationListener的实例,以及它们的作用,在后续的部分会陆续提到。 End!

    [阅读更多...]