SpringFactoriesLoader

Spring工厂加载器,用于将META-INFO/spring.factories文件下的相关接口实现按照K、V形式加载内存中,一个接口多个实现按照“,”分割。如下图所示,SpringFactoriesLoader会将spring.factories中的加载器、监听器初始化器、后置处理器配置类等进行加载。我们可以自定义starter,在spring.factories文件定义自己内容

# PropertySource Loaders
org.springframework.boot.env.PropertySourceLoader=
org.springframework.boot.env.PropertiesPropertySourceLoader,
org.springframework.boot.env.YamlPropertySourceLoader

# Run Listeners
org.springframework.boot.SpringApplicationRunListener=
org.springframework.boot.context.event.EventPublishingRunListener

# Application Context Initializers
org.springframework.context.ApplicationContextInitializer=
org.springframework.boot.context.ConfigurationWarningsApplicationContextInitializer,
org.springframework.boot.context.ContextIdApplicationContextInitializer,
org.springframework.boot.context.config.DelegatingApplicationContextInitializer,
org.springframework.boot.context.embedded.ServerPortInfoApplicationContextInitializer

# Application Listeners
org.springframework.context.ApplicationListener=
org.springframework.boot.ClearCachesApplicationListener,
org.springframework.boot.builder.ParentContextCloserApplicationListener,
org.springframework.boot.context.FileEncodingApplicationListener,
org.springframework.boot.context.config.AnsiOutputApplicationListener,
org.springframework.boot.context.config.ConfigFileApplicationListener,
org.springframework.boot.context.config.DelegatingApplicationListener,
org.springframework.boot.liquibase.LiquibaseServiceLocatorApplicationListener,
org.springframework.boot.logging.ClasspathLoggingApplicationListener,
org.springframework.boot.logging.LoggingApplicationListener

# Environment Post Processors
org.springframework.boot.env.EnvironmentPostProcessor=
org.springframework.boot.cloud.CloudFoundryVcapEnvironmentPostProcessor,
org.springframework.boot.env.SpringApplicationJsonEnvironmentPostProcessor

# Failure Analyzers
org.springframework.boot.diagnostics.FailureAnalyzer=
org.springframework.boot.diagnostics.analyzer.BeanCurrentlyInCreationFailureAnalyzer,
org.springframework.boot.diagnostics.analyzer.BeanNotOfRequiredTypeFailureAnalyzer,
org.springframework.boot.diagnostics.analyzer.BindFailureAnalyzer,
org.springframework.boot.diagnostics.analyzer.ConnectorStartFailureAnalyzer,
org.springframework.boot.diagnostics.analyzer.NoSuchMethodFailureAnalyzer,
org.springframework.boot.diagnostics.analyzer.NoUniqueBeanDefinitionFailureAnalyzer,
org.springframework.boot.diagnostics.analyzer.PortInUseFailureAnalyzer,
org.springframework.boot.diagnostics.analyzer.ValidationExceptionFailureAnalyzer

# FailureAnalysisReporters
org.springframework.boot.diagnostics.FailureAnalysisReporter=
org.springframework.boot.diagnostics.LoggingFailureAnalysisReporter

我们用SpringApplication的初始化过程讲解SpringFactoriesLoader
SpringApplication(Object… sources)

SpringApplication的构造方法创建一个Spring应用实例

public SpringApplication(Object... sources) {
   initialize(sources);
}

initialize()

初始化方法中,设置初始化器时,获取SpringFactories实例

private void initialize(Object[] sources) {
   if (sources != null && sources.length > 0) {
      this.sources.addAll(Arrays.asList(sources));
   }
   this.webEnvironment = deduceWebEnvironment();
   // 设置初始化器
   setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
   setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
   this.mainApplicationClass = deduceMainApplicationClass();
}

getSpringFactoriesInstances()

private <T> Collection<? extends T> getSpringFactoriesInstances(Class<T> type) {
   return getSpringFactoriesInstances(type, new Class<?>[] {});
}

getSpringFactoriesInstances()

获取类加载器–>加载工厂名称集合–>加载Spring工厂实例集合–>排序

private <T> Collection<? extends T> getSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes,
      Object... args) {
   ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
   // Use names and ensure unique to protect against duplicates
   Set<String> names = new LinkedHashSet<String>(SpringFactoriesLoader.loadFactoryNames(type, classLoader));
   List<T> instances = createSpringFactoriesInstances(type, parameterTypes, classLoader, args, names);
   AnnotationAwareOrderComparator.sort(instances);
   return instances;
}

loadFactoryNames()
去META-INFO/spring.factories中读取相关接口实现信息,并返回

public static final String FACTORIES_RESOURCE_LOCATION = "META-INF/spring.factories";

public static List<String> loadFactoryNames(Class<?> factoryClass, ClassLoader classLoader) {
   String factoryClassName = factoryClass.getName();
   try {
      // 根据类加载器判断如何获取资源,若加载器不为null,则走getResources(),若为null,则走getSystemResources()
      Enumeration<URL> urls = (classLoader != null ? classLoader.getResources(FACTORIES_RESOURCE_LOCATION) :
            ClassLoader.getSystemResources(FACTORIES_RESOURCE_LOCATION));
      List<String> result = new ArrayList<String>();
      while (urls.hasMoreElements()) {
         URL url = urls.nextElement();
         // 根据资源路径加载资源
         Properties properties = PropertiesLoaderUtils.loadProperties(new UrlResource(url));
         // 获取KV中的值(接口实现
         String propertyValue = properties.getProperty(factoryClassName);
         for (String factoryName : StringUtils.commaDelimitedListToStringArray(propertyValue)) {
            result.add(factoryName.trim());
         }
      }
      return result;
   }
   catch (IOException ex) {
      throw new IllegalArgumentException("Unable to load factories from location [" +
            FACTORIES_RESOURCE_LOCATION + "]", ex);
   }
}

getResources()和getSystemResources()的区别

createSpringFactoriesInstances()

创建SpringFactories实例,也就是创建监听器、初始化器、配置类等的实例

private <T> List<T> createSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes,
      ClassLoader classLoader, Object[] args, Set<String> names) {
   List<T> instances = new ArrayList<T>(names.size());
   for (String name : names) {
      try {
         // 使用路径类名创建对应的类
         Class<?> instanceClass = ClassUtils.forName(name, classLoader);
         Assert.isAssignable(type, instanceClass);
         // 获取有参构造方法对象
         Constructor<?> constructor = instanceClass.getDeclaredConstructor(parameterTypes);
         // 返回一个instance
         T instance = (T) BeanUtils.instantiateClass(constructor, args);
         instances.add(instance);
      }
      catch (Throwable ex) {
         throw new IllegalArgumentException("Cannot instantiate " + type + " : " + name, ex);
      }
   }
   return instances;
}

总结:SpringFactoriesLoader会读取META-INFO/spring.factories文件下的接口实现信息并将其进行实例化加载到内存中。这些类可能监听器、初始化器、自动配置类以及后置处理器等。我们可以自定义这些类,编写自己的META-INFO/spring.factories。

原文地址:https://blog.csdn.net/weixin_52457624/article/details/134750158

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任

如若转载,请注明出处:http://www.7code.cn/show_27028.html

如若内容造成侵权/违法违规/事实不符,请联系代码007邮箱suwngjj01@126.com进行投诉反馈,一经查实,立即删除

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注