SpringBoot构造流程源码分析:Web应用类型推断( 二 )


ApplicationContextlnitializer 接口只定义了一-个 initialize 方法 , 代码如下 。 public interface ApplicationContextInitializer {void initialize(C applicationContext);}【SpringBoot构造流程源码分析:Web应用类型推断】ApplicationContextlnitializer 接口的 initialize 方法主要是为了初始化指定的应用上下文 。 而对应的上下文由参数传入 , 参数为 ConfigurableApplicationContext 的子类 。
在完成了 Web 应用类型推断之后 , ApplicationContextlnitializer 便开始进行加载工作 , 该过程可分两步骤:获得相关实例和设置实例 。 对应的方法分别为 getSpringFactoriesInstances和 setlnitializers 。
SpringApplication 中获得实例相关方法代码如下 。
privateCollection getSpringF actoriesInstances(Class type) {return getSpringFactoriesInstances(type, new Class[] {});privateCollection getSpringF actoriesInstances(Class type,Class[] parameterTypes, object... args) {ClassLoader classLoader = getClassLoader();//加载对应配置 , 这里采用 LinkedHashSet 和名称来确保加载的唯一 性Set names = new LinkedHashSet<> (SpringF actoriesLoader . loadF actoryNames (type, classLoader));//创建实例List instances = createSpringFactoriesInstances (type,parameterTypeS,classLoader, args, names);//排序操作AnnotationAwareOrderComparator . sort(instances);return instances;}getSpringFactorieslnstances 方 法 依 然 是 通 过 SpringFactoriesL oader 类 的loadFactoryNames 方法来获得 ME TA-INF/spring.factories 文件中注册的对应配置 。 在Spring Boot 2.2.1 版本中 , 该文件内具体的配置代码如下 。
#应用程序上下文的初始化器配置
org. springframework. context . Applicat ionContextInitializer=\org. springframework . boot . context . Configurat ionWarningsApplicationContextInitializer,\org. springframework. boot . context . ContextIdApplicat ionContextInitializer,\org. springframework . boot. context . config . Delegat ingApplicationContextInitializer, \org. springframework . boot . rsocket . context . RSocketPortInfoApplicat ionContextInitializer,\org. springframework. boot . web . context . ServerPortInfoApplicationContextInitializer配置代码中等号后面的类为接口 ApplicationContextlnitializer 的具体实现类 。 当获取到这些配置类的全限定名之后 , 便可调用 createSpringFactoriesInstances 方法进行相应的实例化操作 。
privateList createSpringFactoriesInstances(Class type,Class[] parameterTypes, ClassLoader classLoader, Object[] args,Set names) {List instances = new ArrayList<>(names. size());//遍历加裁到的类名(全限定名)for (String name : names) {try {//获取 CassClass instanceClass = ClassUtils. forName( name, classLoader);Assert. isAssignable(type, instanceClass);//获取有参构造器Constructor constructor = instanceClass. getDeclaredConstructor (parameterTypes);//创建对象「instance = (T) BeanUtils . instantiateClass( constructor, args);instances . add(instance);} catch (Throwable ex) {throw new IllegalArgumentException("Cannot instantiate " + type +”:”+ name, ex);}return instances;}完成获取配置类集合和实例化操作之后 , 调用 setlnitializers 方法将实例化的集合添加到SprinaApplication的成员变量initializers中 , 类型为