diff --git "a/springboot-source-code-analysis/(3)345円267円245円345円216円202円345円212円240円350円275円275円346円234円272円345円210円266円350円247円243円346円236円220円.md" "b/springboot-source-code-analysis/(3)345円267円245円345円216円202円345円212円240円350円275円275円346円234円272円345円210円266円350円247円243円346円236円220円.md" index 63934d4..cd2d8b8 100644 --- "a/springboot-source-code-analysis/(3)345円267円245円345円216円202円345円212円240円350円275円275円346円234円272円345円210円266円350円247円243円346円236円220円.md" +++ "b/springboot-source-code-analysis/(3)345円267円245円345円216円202円345円212円240円350円275円275円346円234円272円345円210円266円350円247円243円346円236円220円.md" @@ -39,3 +39,148 @@ public final class SpringFactoriesLoader { image-20210616203348022 + + +#### 源码阅读 + +##### 1、首先通过setInitializers#()方法设置系统初始化器 + +```java + @SuppressWarnings({ "unchecked", "rawtypes" }) + public SpringApplication(ResourceLoader resourceLoader, Class... primarySources) { + this.resourceLoader = resourceLoader; + Assert.notNull(primarySources, "PrimarySources must not be null"); + this.primarySources = new LinkedHashSet(Arrays.asList(primarySources)); + this.webApplicationType = WebApplicationType.deduceFromClasspath(); + // 通过setInitializers#()方法,设置系统初始化器 + setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class)); + setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class)); + this.mainApplicationClass = deduceMainApplicationClass(); + } +``` + + + +##### 2、获取系统初始化器实现的全路径名,为它们创建实例子,最终把它们进行排序后注入到Spring容器集合中 + +```java + private Collection getSpringFactoriesInstances(Class type, Class[] parameterTypes, Object... args) { + // 获得类加载器 + ClassLoader classLoader = getClassLoader(); + // 通过这个SpringFactoriesLoader#loadFactoryNames方法获取Spring中所有系统初始化器实现的全路径名 + Set names = new LinkedHashSet(SpringFactoriesLoader.loadFactoryNames(type, classLoader)); + // 通过createSpringFactoriesInstances#()创建它们的实例 + List instances = createSpringFactoriesInstances(type, parameterTypes, classLoader, args, names); + // 通过注解@Order进行排序 + AnnotationAwareOrderComparator.sort(instances); + return instances; + } +``` + + + +##### 3、获取系统初始化器实现的全路径名 + +```java + private static Map> loadSpringFactories(@Nullable ClassLoader classLoader) { + MultiValueMap result = cache.get(classLoader); + // 检查是否有缓存 + if (result != null) { + return result; + } + + try { + Enumeration urls = (classLoader != null ? + // 获取 META-INF/spring.factories下所有系统初始化器的实现 + classLoader.getResources(FACTORIES_RESOURCE_LOCATION) : + ClassLoader.getSystemResources(FACTORIES_RESOURCE_LOCATION)); + result = new LinkedMultiValueMap(); + while (urls.hasMoreElements()) { + URL url = urls.nextElement(); + UrlResource resource = new UrlResource(url); + // 通过url路径,获取spring.factories中的配置,并将其转成Properties格式 + Properties properties = PropertiesLoaderUtils.loadProperties(resource); + for (Map.Entry entry : properties.entrySet()) { + String factoryClassName = ((String) entry.getKey()).trim(); + for (String factoryName : StringUtils.commaDelimitedListToStringArray((String) entry.getValue())) { + // 将初始化器的包名进行返回 + result.add(factoryClassName, factoryName.trim()); + } + } + } + // 记录到缓存中 + cache.put(classLoader, result); + return result; + } + catch (IOException ex) { + throw new IllegalArgumentException("Unable to load factories from location [" + + FACTORIES_RESOURCE_LOCATION + "]", ex); + } + } +``` + + + +##### 4、创建初始化器的实例 + +```java + @SuppressWarnings("unchecked") + private List createSpringFactoriesInstances(Class type, Class[] parameterTypes, + ClassLoader classLoader, Object[] args, Set names) { + List instances = new ArrayList(names.size()); + for (String name : names) { + try { + // 通过反射获取具体实现,并完成类的初始化,最终返回实现类的实例 + Class instanceClass = ClassUtils.forName(name, classLoader); + Assert.isAssignable(type, instanceClass); + Constructor constructor = instanceClass.getDeclaredConstructor(parameterTypes); + T instance = (T) BeanUtils.instantiateClass(constructor, args); + instances.add(instance); + } + catch (Throwable ex) { + throw new IllegalArgumentException("Cannot instantiate " + type + " : " + name, ex); + } + } + return instances; + } +``` + + + +##### 5、按@Order注解进行排序 + +```java + private Collection getSpringFactoriesInstances(Class type, Class[] parameterTypes, Object... args) { + ClassLoader classLoader = getClassLoader(); + // Use names and ensure unique to protect against duplicates + Set names = new LinkedHashSet(SpringFactoriesLoader.loadFactoryNames(type, classLoader)); + List instances = createSpringFactoriesInstances(type, parameterTypes, classLoader, args, names); + // 按@Order注解进行排序,值约小的越靠前 + AnnotationAwareOrderComparator.sort(instances); + return instances; + } +``` + + + +##### 6、将初始化器排序好的实例注册到Spring容器中 + +```java + public void setInitializers(Collection> initializers) { + this.initializers = new ArrayList(); + // 将初始化器的实例添加到Spring容器中 + this.initializers.addAll(initializers); + } +``` + + + +#### 总结 + +- SpringFactoriesLoader作用: SpringBoot框架中从类路径jar包中读取特定的文件(META-INF/spring.factories)实现扩展类的载入 + +image-20210726172128392 + +- LoadFactories流程 + +image-20210726172754618

AltStyle によって変換されたページ (->オリジナル) /