springboot中getSpringFactoriesInstances源码的示例分析
发表于:2024-09-22 作者:千家信息网编辑
千家信息网最后更新 2024年09月22日,这篇文章主要介绍了springboot中getSpringFactoriesInstances源码的示例分析,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带
千家信息网最后更新 2024年09月22日springboot中getSpringFactoriesInstances源码的示例分析
这篇文章主要介绍了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安全错误
数据库的锁怎样保障安全
数据库介绍 英语作文
滁州游戏服务器诚信企业推荐
访问实时数据库
梦幻西游服务器被删除
陈酿数据库是谁 老蛮
陕西销售软件开发排行
剑灵三区哪个服务器人多
无字天书小说软件开发
软件开发有难度吗
湖南一路畅行互联网科技
vb数据库只读
入网终端网络安全检测
数据库防伪技术服务至上
中国高通网络安全
网络安全与执法培养
软件开发的工作好不好的
张家口原装服务器厂家
计算机网络技术适合零基础吗
汽车仪表软件开发工程师
今日网络安全关键词
服务器安装数据库是要干嘛的
华为手机ai数据库
删除用户账号的命令数据库
网络安全调查创新项目
视易语音点歌 服务器
上海铂傲软件开发有限公司
苏州李晶任网络安全保卫支队政委
同有服务器
c#数据库复选框选中事件
关掉ftp服务器管理