springboot中getSpringFactoriesInstances源码的示例分析
发表于:2025-02-10 作者:千家信息网编辑
千家信息网最后更新 2025年02月10日,这篇文章主要介绍了springboot中getSpringFactoriesInstances源码的示例分析,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带
千家信息网最后更新 2025年02月10日springboot中getSpringFactoriesInstances源码的示例分析image image
这篇文章主要介绍了springboot中getSpringFactoriesInstances源码的示例分析,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。
一、概述及流程图
在springboot启动过程中,getSpringFactoriesInstances这个方法很重要,启动的时候使用该方法从classpath上所有jar包中找出对应的META-INF/spring.factorys属性文件,并将其中的初始化器和监听器加载并实例化,应用于更进一步的初始化工作。其工作流程图如下:
二、源码解析
让我们跟着流程图和时序图一步步窥视其中的奥妙:
调用getSpringFactoriesInstances()方法
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();
//1.加载初始化器并实例化,10.并赋值给initializers
setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
//同上,监听器
setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
//推断应用主类
this.mainApplicationClass = deduceMainApplicationClass();
}
获取类加载器和调用loadFactoryNames()方法及对返回结果进行初始化以及排序
private Collection getSpringFactoriesInstances(Class type) {
return getSpringFactoriesInstances(type, new Class>[] {});
}
private Collection getSpringFactoriesInstances(Class type, Class>[] parameterTypes, Object... args) {
//2. 获取类加载器
ClassLoader classLoader = getClassLoader();
// Use names and ensure unique to protect against duplicates
//3. 调用loadFactoryNames方法,并使用set对其返回结果进行去重处理
Set names = new LinkedHashSet<>(SpringFactoriesLoader.loadFactoryNames(type, classLoader));
//9. 实例化初始化器
List instances = createSpringFactoriesInstances(type, parameterTypes, classLoader, args, names);
//9. 对实例化的结果进行排序
AnnotationAwareOrderComparator.sort(instances);
return instances;
}
//该方法主要是通过反射实例化初始化器
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;
}
查询缓存和读取META-INFO/spring.factorys文件key-value值,并对value值进行处理
public static List loadFactoryNames(Class> factoryClass, @Nullable ClassLoader classLoader) {
String factoryClassName = factoryClass.getName();
// 返回初始化器的value值
return loadSpringFactories(classLoader).getOrDefault(factoryClassName, Collections.emptyList());
}
private static Map> loadSpringFactories(@Nullable ClassLoader classLoader) {
MultiValueMap result = //查询缓存,如果有就返回,没有就加载
cache.get(classLoader);
if (result != null) {
return result;
}
try {
//通过类加载器加载所有jar包中包含META-INFO/spring.factorys的文件资源路径
Enumeration urls = (classLoader != null ?
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);
//实例化properties对象,并加载路径中的spring.factorys文件内容
Properties properties = PropertiesLoaderUtils.loadProperties(resource);
for (Map.Entry, ?> entry : properties.entrySet()) {
String factoryClassName = ((String)
//获取key值
entry.getKey()).trim();
//对value值进行都好拆分处理
for (String factoryName : StringUtils.commaDelimitedListToStringArray((String) entry.getValue())) {
//将key和value值存入result中 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);
}
}
感谢你能够认真阅读完这篇文章,希望小编分享的"springboot中getSpringFactoriesInstances源码的示例分析"这篇文章对大家有帮助,同时也希望大家多多支持,关注行业资讯频道,更多相关知识等着你来学习!
实例
方法
文件
篇文章
结果
源码
流程
流程图
缓存
路径
处理
示例
分析
监听器
资源
工作
应用
排序
推断
查询
数据库的安全要保护哪些东西
数据库安全各自的含义是什么
生产安全数据库录入
数据库的安全性及管理
数据库安全策略包含哪些
海淀数据库安全审计系统
建立农村房屋安全信息数据库
易用的数据库客户端支持安全管理
连接数据库失败ssl安全错误
数据库的锁怎样保障安全
怎么实现关系型数据库
人才数据库建设初衷
传奇神龙帝国怪物数据库
代码添加数据库
网络技术市场需求调查报告
盈环网络技术两江分公司
软件开发相关股票
正规网络技术开发服务至上
中国网络安全教育平台登录入口
京东计算机网络技术的使用情况
数据库的+查询+插入+修改
触摸屏内置数据库
gpr怎么刷新数据库
游侠饥荒如何开服务器
现代通信网论文新的网络技术
用友附加数据库
昭通软件开发专业好吗
ibm服务器监控
sql跨服务器可以连接索引吗
魔兽世界联盟服务器插件
网络安全的管理信息写作
软件开发如何开始
电脑的网络安全密钥怎么设置
新炬网络技术杭州待遇
西安开发小程序需要什么服务器
正规网络技术开发服务至上
服务器管理用户名密码
网络安全 党的领导
电脑我的世界网易服务器秒退
服务器安全狗+密码忘记