springfactoriesloader
时间: 2023-04-15 09:04:54 浏览: 59
SpringFactoriesLoader是Spring框架中的一个工具类,用于加载META-INF/spring.factories文件中定义的工厂类。这些工厂类可以用于创建各种Spring框架中的组件,例如BeanPostProcessor、BeanFactoryPostProcessor、ApplicationListener等。SpringFactoriesLoader可以通过ClassLoader加载META-INF/spring.factories文件,并返回其中定义的工厂类的实例。这样,开发人员就可以通过配置META-INF/spring.factories文件来扩展Spring框架的功能。
相关问题
springfactoriesloader如何实现
SpringFactoriesLoader 是 Spring 框架中一个非常重要的工具类,它可以用于实现插件化架构。该工具类可以从类路径下的 `META-INF/spring.factories` 文件中加载指定的配置信息,然后将这些配置信息实例化为具体的对象并返回。
SpringFactoriesLoader 的实现原理主要分为两个步骤:
1. 获取 `META-INF/spring.factories` 配置文件中的所有配置信息,通过 `ClassLoader.getResources()` 方法获取到所有的 `spring.factories` 文件,然后解析文件内容,将其中的配置信息存储到一个 `Map<Class<?>, List<String>>` 中。
2. 根据配置信息创建对应的对象实例,遍历上述的 `Map`,对于每一个键值对,获取其对应的类和实现类列表,然后使用 `Class.forName(className)` 方法加载对应的实现类,并通过反射创建实例对象。最后将创建的实例对象添加到一个 List 中并返回。
下面是 SpringFactoriesLoader 的部分源码:
```java
public static <T> List<T> loadFactories(Class<T> factoryClass, ClassLoader classLoader) {
String factoryClassName = factoryClass.getName();
return loadFactories(factoryClass, classLoader).stream()
.map(className -> {
try {
Class<?> clazz = ClassUtils.forName(className, classLoader);
if (!factoryClass.isAssignableFrom(clazz)) {
throw new IllegalArgumentException(
"Class [" + className + "] is not assignable to [" + factoryClassName + "]");
}
return (T) BeanUtils.instantiateClass(clazz);
}
catch (Throwable ex) {
throw new IllegalArgumentException(
"Unable to instantiate factory class [" + className + "] for factory type [" +
factoryClassName + "]", ex);
}
}).collect(Collectors.toList());
}
public static List<String> loadFactoryNames(Class<?> factoryClass, ClassLoader classLoader) {
String factoryClassName = factoryClass.getName();
return loadSpringFactories(classLoader).getOrDefault(factoryClassName, Collections.emptyList());
}
private static Map<String, List<String>> loadSpringFactories(ClassLoader classLoader) {
MultiValueMap<String, String> result = cache.get(classLoader);
if (result != null) {
return result;
}
try {
Enumeration<URL> urls = classLoader.getResources(FACTORIES_RESOURCE_LOCATION);
result = new LinkedMultiValueMap<>();
while (urls.hasMoreElements()) {
URL url = urls.nextElement();
UrlResource resource = new UrlResource(url);
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);
}
}
```
通过上述代码可以看出,SpringFactoriesLoader 的实现主要依赖于 `ClassLoader.getResources()` 方法和 `PropertiesLoaderUtils.loadProperties()` 方法来加载 `spring.factories` 配置文件,并解析其中的配置信息。然后通过反射创建实现类的实例对象,最后返回实例对象列表。
springboot3项目启动,报错Exception in thread "main" java.lang.NoSuchMethodError:org.springframework.core.io.support.SpringFactoriesLoader
.loadFactoryNames(Ljava/lang/Class;Ljava/lang/ClassLoader;)Ljava/util/List;
这个错误是由于版本不兼容导致的。可能是因为您使用了不兼容的 Spring 版本。建议您检查您的 pom.xml 文件,确保所有的 Spring 依赖都使用相同的版本。如果问题仍然存在,您可以尝试在 pom.xml 文件中添加 exclusions 确保不会有冲突的库被引入。