【Spring Boot 源码学习】SpringApplication 的 run 方法核心流程介绍

news2024/11/25 11:06:29

《Spring Boot 源码学习系列》

在这里插入图片描述

SpringApplication 的 run 方法核心流程介绍

  • 一、引言
  • 二、往期内容
  • 三、主要内容
    • 3.1 run 方法源码初识
    • 3.2 引导上下文 BootstrapContext
    • 3.3 系统属性【java.awt.headless】
    • 3.4 早期启动阶段
    • 3.5 准备和配置应用环境
    • 3.6 打印 Banner 信息
    • 3.7 新建应用上下文
    • 3.8 准备和配置应用上下文
    • 3.9 刷新应用上下文
    • 3.10 afterRefresh 方法
    • 3.11 打印启动日志
    • 3.12 Spring 容器启动完成
    • 3.13 callRunners 方法
    • 3.14 Spring 容器正在运行中
    • 3.15 异常处理
  • 四、总结

一、引言

在前面的博文《初识 SpringApplication》中,Huazie 带大家一起分析了 SpringApplication 类实例化的逻辑。当 SpringApplication 对象被创建之后,我们就可以调用它的 run 方法来启动和运行 Spring Boot 项目。

本篇博文将围绕 SpringApplicationrun 方法展开,带大家一起从源码分析 Spring Boot 的运行流程。

在这里插入图片描述

二、往期内容

在开始本篇的内容介绍之前,我们先来看看往期的系列文章【有需要的朋友,欢迎关注系列专栏】:

Spring Boot 源码学习
Spring Boot 项目介绍
Spring Boot 核心运行原理介绍
【Spring Boot 源码学习】@EnableAutoConfiguration 注解
【Spring Boot 源码学习】@SpringBootApplication 注解
【Spring Boot 源码学习】走近 AutoConfigurationImportSelector
【Spring Boot 源码学习】自动装配流程源码解析(上)
【Spring Boot 源码学习】自动装配流程源码解析(下)
【Spring Boot 源码学习】深入 FilteringSpringBootCondition
【Spring Boot 源码学习】OnClassCondition 详解
【Spring Boot 源码学习】OnBeanCondition 详解
【Spring Boot 源码学习】OnWebApplicationCondition 详解
【Spring Boot 源码学习】@Conditional 条件注解
【Spring Boot 源码学习】HttpEncodingAutoConfiguration 详解
【Spring Boot 源码学习】RedisAutoConfiguration 详解
【Spring Boot 源码学习】JedisConnectionConfiguration 详解
【Spring Boot 源码学习】初识 SpringApplication
【Spring Boot 源码学习】Banner 信息打印流程
【Spring Boot 源码学习】自定义 Banner 信息打印
【Spring Boot 源码学习】BootstrapRegistryInitializer 详解
【Spring Boot 源码学习】ApplicationContextInitializer 详解
【Spring Boot 源码学习】ApplicationListener 详解
【Spring Boot 源码学习】SpringApplication 的定制化介绍
【Spring Boot 源码学习】BootstrapRegistry 详解
【Spring Boot 源码学习】深入 BootstrapContext 及其默认实现
【Spring Boot 源码学习】BootstrapRegistry 初始化器实现
【Spring Boot 源码学习】BootstrapContext的实际使用场景
【Spring Boot 源码学习】深入 ApplicationContext 初始化器实现
【Spring Boot 源码学习】共享 MetadataReaderFactory 上下文初始化器
【Spring Boot 源码学习】ConditionEvaluationReport 日志记录上下文初始化器

三、主要内容

注意: 以下涉及 Spring Boot 源码 均来自版本 2.7.9,其他版本有所出入,可自行查看源码。

3.1 run 方法源码初识

在这里插入图片描述

上述截图就是 SpringApplicationrun 方法核心代码。

下面 Huazie 将带着大家一起通读这块源码,从整体上了解下 run 方法核心流程。

3.2 引导上下文 BootstrapContext

DefaultBootstrapContext bootstrapContext = createBootstrapContext();

翻看 DefaultBootstrapContext 的源码可知,从 Spring Boot 2.4.0 版本开始支持引导上下文。

在这里插入图片描述

在《BootstrapRegistryInitializer 详解》中,Huazie 带大家详细分析了加载并初始化 BootstrapRegistryInitializer 的逻辑。而这里的 createBootstrapContext 方法就是用于创建默认的引导上下文对象 DefaultBootstrapContext,并利用 BootstrapRegistry 初始化器初始化该引导上下文对象。

想深入了解的朋友们,可查看 Huazie 下面列出的博文:

  • 《BootstrapRegistry 详解》
  • 《深入 BootstrapContext 及其默认实现》
  • 《BootstrapRegistry 初始化器实现》
  • 《BootstrapContext的实际使用场景》

3.3 系统属性【java.awt.headless】

private static final String SYSTEM_PROPERTY_JAVA_AWT_HEADLESS = "java.awt.headless";

// 配置 java.awt.headless 系统属性
private void configureHeadlessProperty() {
	System.setProperty(SYSTEM_PROPERTY_JAVA_AWT_HEADLESS,
			System.getProperty(SYSTEM_PROPERTY_JAVA_AWT_HEADLESS, Boolean.toString(this.headless)));
}

java.awt.headlessJava 中的一个系统属性,用于指示 Java 应用程序是否运行在 Headless 模式下。Headless 模式是指系统缺少显示设备、键盘或鼠标的状态,通常应用于服务器环境,如应用集群、数据库集群等,这些环境通常通过网络远程操作,没有实际的显示设备。

Java 中,AWT(Abstract Window Toolkit) 是用于构建图形用户界面(GUI)应用的标准 API 接口。

JavaAWT 提供了两种模式实现以适应不同的运行环境:

  • 标准模式,适用于具有可用显示设备、驱动和图形用户界面的环境。
  • Headless 模式 ,适用于没有显示设备、驱动或图形用户界面的环境,例如服务器。

注意: 设置 java.awt.headless 属性为 true 会使 Java AWT 工具包在 headless 模式下运行,这意味着它将不会尝试加载或访问与图形用户界面相关的资源或功能。

3.4 早期启动阶段

SpringApplicationRunListeners listeners = getRunListeners(args);
listeners.starting(bootstrapContext, this.mainApplicationClass);

SpringApplicationRunListeners 中包含了一组 SpringApplicationRunListener 的集合。SpringApplicationRunListenerSpringApplicationrun 方法的监听器,它用来监听 Spring Boot 应用的不同启动阶段,这些阶段都会发布对应的事件。

这里 starting 方法,就对应了最早期的启动阶段,它在 run 方法刚开始执行时就被立即调用。starting 方法里会发布 ApplicationStartingEvent 事件,通过监听该事件,应用可以执行一些非常早期的初始化工作,比如配置系统属性、初始化基础组件等等。

3.5 准备和配置应用环境

ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
ConfigurableEnvironment environment = prepareEnvironment(listeners, bootstrapContext, applicationArguments);
configureIgnoreBeanInfo(environment);

ApplicationArgumentsSpring Boot 中用于获取命令行参数的接口,其默认实现是 DefaultApplicationArguments

prepareEnvironment 方法用于准备和配置应用程序的运行时环境,它会发布 ApplicationEnvironmentPreparedEvent 事件,通过监听该事件,应用程序可以执行一系列操作来准备和配置其运行环境。其返回的 ConfigurableEnvironment 对象,包含了应用程序的所有配置信息。

通过 ConfigurableEnvironment 对象,我们可以获取特定配置属性的值,也可以在运行时动态修改配置属性。

我们来看看 configureIgnoreBeanInfo 方法:

在这里插入图片描述

在这里插入图片描述

configureIgnoreBeanInfo 方法中,可以看到如下代码:

Boolean ignore = environment.getProperty(CachedIntrospectionResults.IGNORE_BEANINFO_PROPERTY_NAME,
				Boolean.class, Boolean.TRUE);

从上述代码中,可以看到通过 environment 变量获取属性名为 spring.beaninfo.ignore 的属性值,其 getProperty 方法有三个参数:

  • 第一个参数是属性名。
  • 第二个参数是期望返回的属性值的类型,这里是 Boolean.class
  • 第三个参数是默认值,如果找不到属性或者属性不能被转换为 Boolean 类型,则使用 Boolean.TRUE 作为默认值。

系统属性 spring.beaninfo.ignore 用于指示 Spring 在调用 JavaBeans Introspector 时使用Introspector.IGNORE_ALL_BEANINFO 模式。如果此属性的值为 true,则 Spring 会跳过搜索 BeanInfo 类(通常适用于以下情况:应用程序中的 beans 从一开始就没有定义这样的类)。

默认值是 false,表示 Spring 会考虑所有的 BeanInfo 元数据类,就像标准 Introspector.getBeanInfo(Class) 调用那样。如果在启动时或延迟加载时,反复访问不存在的 BeanInfo 类开销很大,可以考虑将此标志切换为 true

请注意:如果存在反复访问不存在的 BeanInfo 类,可能也表明缓存未奏效。最好将 Springjar 包与应用类放在同一个 ClassLoader 中,这样可以在任何情况下与应用程序的生命周期一起进行干净的缓存。对于 Web 应用程序,如果采用多 ClassLoader 布局,可以考虑在 web.xml 中声明一个本地的 org.springframework.web.util.IntrospectorCleanupListener,这也可以实现有效的缓存。

3.6 打印 Banner 信息

Banner printedBanner = printBanner(environment);

printBanner 方法用于 Spring Boot 启动时的 Banner 信息打印。

想要深入了解 Banner 打印的读者们,请查看如下博文:

  • 《Banner 信息打印流程》
  • 《自定义 Banner 信息打印》

3.7 新建应用上下文

ConfigurableApplicationContext context = createApplicationContext();

protected ConfigurableApplicationContext createApplicationContext() {
	return this.applicationContextFactory.create(this.webApplicationType);
}

上述 createApplicationContext 方法的功能是:根据给定的 Web 应用程序类型 webApplicationType 创建一个可配置的应用上下文对象 ConfigurableApplicationContext

在《初识 SpringApplication》这篇博文的 2.2 小节Web 应用类型推断】中,大家可以看到 Web 应用程序类型 webApplicationType 是如何获取的,这里不赘述了,感兴趣的可以自行查看。

3.8 准备和配置应用上下文

context.setApplicationStartup(this.applicationStartup);
prepareContext(bootstrapContext, context, environment, listeners, applicationArguments, printedBanner);

setApplicationStartup 方法用于设置当前应用上下文的 ApplicationStartup ,这允许应用上下文在启动期间记录指标。

prepareContext 方法用于准备和配置应用程序上下文,这里会依次发布如下事件:

  1. ApplicationContextInitializedEvent:当 SpringApplication 启动并且 ApplicationContext 已准备好,且 ApplicationContextInitializer 集合已被调用,但在加载任何 bean 定义之前,将发布该事件。
  2. ApplicationPreparedEvent :当 SpringApplication 启动并且 ApplicationContext 已经完全准备好但尚未刷新时,将发布事件。在此阶段,bean 定义将被加载,环境已经准备好可以使用。

3.9 刷新应用上下文

static final SpringApplicationShutdownHook shutdownHook = new SpringApplicationShutdownHook();

refreshContext(context);

private void refreshContext(ConfigurableApplicationContext context) {
	if (this.registerShutdownHook) {
		shutdownHook.registerApplicationContext(context);
	}
	refresh(context);
}

protected void refresh(ConfigurableApplicationContext applicationContext) {
    applicationContext.refresh();
}

registerShutdownHook 变量表示是否应注册一个关闭钩子,默认为 true

SpringApplicationShutdownHook 是一个用于执行 Spring Boot 应用程序优雅关闭的 Runnable 关机钩子。这个钩子跟踪已注册的应用程序上下文以及通过 SpringApplication.getShutdownHandlers() 注册的任何操作。

refreshContext 方法里面可以看到调用 refresh 方法,refresh 方法里面则是调用 ConfigurableApplicationContext【实现类是 AbstractApplicationContext ,该类属于 spring-context 包】的 refresh 方法,该方法是用来刷新底层的应用上下文。

它会加载或刷新配置的持久化表示,这可能来自基于 Java 的配置、XML 文件、属性文件、关系数据库模式或其他某种格式。调用此方法后,要么实例化所有单例对象,要么不实例化任何单例对象。

它最后会发布 ContextRefreshedEvent 事件,通过监听该事件,可以执行一些应用上下文初始化或刷新后需要进行的操作。

3.10 afterRefresh 方法

刷新应用上下文之后,调用 afterRefresh 方法。该方法的实现默认为空,可由开发人员自行扩展。

在这里插入图片描述

3.11 打印启动日志

long startTime = System.nanoTime();

Duration timeTakenToStartup = Duration.ofNanos(System.nanoTime() - startTime);
if (this.logStartupInfo) {
	new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), timeTakenToStartup);
}

System.nanoTime() 用于获取当前时间的纳秒值。

Duration.ofNanos() 用于将纳秒数转换为 Duration 对象,timeTakenToStartup 表示 Spring Boot 应用启动所需的时间。

logStartupInfo 表示是否需要记录启动信息,如果为 true,则需要记录启动信息。

StartupInfoLogger 类用于在应用程序启动时记录应用信息,其中 logStarted 方法用于以 INFO 日志级别打印应用启动时间。

在这里插入图片描述
在这里插入图片描述

实际运行日志信息类似如下:

在这里插入图片描述

3.12 Spring 容器启动完成

listeners.started(context, timeTakenToStartup);

这里表示上下文已经刷新,应用程序已经启动,但是 CommandLineRunnersApplicationRunners 尚未被调用。

SpringApplicationRunListenersstarted 方法里会发布 ApplicationStartedEvent 事件,通知监听器 Spring 容器启动完成。

3.13 callRunners 方法

callRunners(context, applicationArguments);

callRunners 方法里面会调用 ApplicationRunnerCommandLineRunner 的运行方法。

在这里插入图片描述

通过阅读上述代码,可以总结如下:

  • 首先,从 context 中获取类型为 ApplicationRunnerCommandLineRunnerBean
  • 接着,将它们放入 List 列表中,并进行排序。
  • 最后,再遍历排序后的 ApplicationRunnerCommandLineRunnerBean,并调用它们的 run 方法。

Spring Boot 提供 ApplicationRunnerCommandLineRunner 这两种接口,是为了通过它们来实现在容器启动时执行一些操作。在同一个应用上下文中可以定义多个 ApplicationRunnerCommandLineRunnerbean,并可以使用 Ordered 接口或 @Order 注解进行排序。

ApplicationRunnerCommandLineRunner 这两个接口都有一个 run 方法,但不同之处是:

  • ApplicationRunnerrun 方法的参数为 ApplicationArguments
  • CommandLineRunnerrun 方法的参数为 字符串数组

如果需要访问 ApplicationArguments 而不是原始的字符串数组,大家可以考虑使用 ApplicationRunner

3.14 Spring 容器正在运行中

Duration timeTakenToReady = Duration.ofNanos(System.nanoTime() - startTime);
listeners.ready(context, timeTakenToReady);

这里表示应用上下文已经刷新,所有的 CommandLineRunnersApplicationRunners 都已被调用,应用程序已准备好处理请求。

SpringApplicationRunListenersready 方法里会发布 ApplicationReadyEvent 事件,通知监听器 Spring 容器正在运行中。

Spring Boot 2.6.0 版本之前,大家看到调用的是 SpringApplicationRunListenerrunning 方法。从 Spring Boot 2.6.0 版本开始,新增了 ready 方法替代 running 方法。在 Spring Boot 3.0.0 版本中正式去除 running 方法。

在这里插入图片描述

3.15 异常处理

handleRunFailure(context, ex, listeners);

3.53.13 小节 ,如果出现异常,则会捕获后调用 handleRunFailure 进行异常处理。

3.14 小节,同样它如果出现异常,也会捕获后调用 handleRunFailure 进行异常处理。

handleRunFailure 方法里会发布 ApplicationFailedEvent 事件,通过监听该事件,开发人员可以实现如下的一些操作:

  • 错误日志记录:当应用启动失败时,可以记录详细的错误信息到日志文件中,便于后续的问题排查和分析。
  • 通知发送:在应用启动失败时,可以发送通知给相关的开发或运维人员,以便他们能够及时响应并处理问题。
  • 数据备份:如果应用在启动过程中出现异常,可能需要对某些关键数据进行备份,以防止数据丢失。
  • 资源清理:在应用启动失败的情况下,可能需要释放或清理已经分配的资源,如数据库连接、文件句柄等。
  • 尝试自动恢复:在某些情况下,可以尝试自动重启应用或者执行其他恢复操作,以减少人工干预的需求。
  • 自定义处理逻辑:根据具体的业务需求,实现自定义的错误处理逻辑,比如回滚事务、关闭网络连接等。

有关这块更详细的内容,后续 Huazie 将专门出一篇讲解,敬请期待!!!

四、总结

本篇 Huazie 向大家初步介绍了 SpringApplicationrun 方法核心流程。由于篇幅受限,其中很多环节并未深入讲解,后续 Huazie 将会针对这些内容深入分析,和大家一起从源码详细了解 Spring Boot 的运行流程。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1588094.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

一起学习python——基础篇(16)

今天继续说说python的网络请求方法——get方法和post方法。上一章已经简单说了一下get方法,现在说一下post方法如何进行网络请求。 假如服务端开发人员给你一个接口文档内容如下: Request(请求参数): 1、接口url为http://127.0.0.1:5005/a…

Mac 局域网内连接 MySQL

1. 前言 本文记录在 mac 局域网下实现数据库资源共享的问题 项目开发初期,都是在本地进行开发调试,数据库也在本地。那么和你配合开发的同事,就可能想要连接你 mac 电脑的数据库,连接过程中可能就会遇到问题。本文详细记录这些问…

MongoDB数据库转换为表格文件的Python实现

目录 一、引言 二、转换工具与库的选择 三、转换过程详解 安装必要的库 连接MongoDB数据库 查询并处理数据 将数据写入CSV文件 四、进阶技巧与注意事项 五、总结 一、引言 在当今大数据时代,数据的存储、处理与共享显得尤为重要。MongoDB作为一个面向文档…

centos7安装 on-my-zsh

如下👇 yum install -y zsh chsh -s /bin/zsh yum install -y git sh -c "$(curl -fsSL https://raw.githubusercontent.com/robbyrussell/oh-my-zsh/master/tools/install.sh)" 重启即可生效啦~

cordova后台插件开发新手教程

typora-root-url: imags cordova后台插件开发新手教程 预安装环境:JDK11、Android studios、nodo.js 一、环境搭建 1.安装Cordova npm install -g cordova2.创建项目 cordova create 具体命令: cordova create 目录名 包名 项目名 执行结果终端&am…

7-23 币值转换

题目链接&#xff1a;7-23 币值转换 一. 题目 1. 题目 2. 输入输出样例 3. 限制 二、代码 1. 代码实现 #include <iostream> #include <string> using namespace std;string numStr[] { // 0-9对应的字符串&#xff08;字符串是方便string&#xff09;"a…

tensorflow.js 如何从 public 路径加载人脸特征点检测模型

系列文章目录 如何在前端项目中使用opencv.js | opencv.js入门如何使用tensorflow.js实现面部特征点检测tensorflow.js 如何从 public 路径加载人脸特征点检测模型tensorflow.js 如何使用opencv.js通过面部特征点估算脸部姿态并绘制示意图tensorflow.js 使用 opencv.js 将人脸…

常用特征分箱算法

特征分箱是构建信用评分过程中最重要的一个环节。特征分箱是对连续变量离散化的一种简称&#xff0c;对于连续型变量&#xff0c;需要对其连续值进行拆分&#xff0c;并进行后续的分箱调整工作&#xff1b; 对于离散型变量&#xff0c;通常要根据每个离散值计算其坏样本占比或…

【unity】【C#】游戏音乐播放和发布

今天我们来认识一下有关 unity 音乐的一些知识 我们先创建 AudioClips 文件夹&#xff0c;这个文件夹通常就是 unity 中存放音乐的文件夹&#xff0c;然后拖进音乐文件进去 这里为大家提供了两个音乐&#xff0c;有需要可以自取 百度网盘&#xff1a;https://pan.baidu.com/s…

从库延迟案例分析

背景介绍 近来一套业务系统&#xff0c;从库一直处于延迟状态&#xff0c;无法追上主库&#xff0c;导致业务风险较大。从资源上看&#xff0c;从库的CPU、IO、网络使用率较低&#xff0c;不存在服务器压力过高导致回放慢的情况&#xff1b;从库开启了并行回放&#xff1b;在从…

一键提升Edge浏览器生产力

Edge作为微软的产品&#xff0c;其具体使用和特性在此不再赘述&#xff0c;其中对我个人而言较有吸引力的部分是其扩展部分。正是有了其丰富的扩展插件&#xff0c;其生产力才能一键跃升&#xff0c;今天让我们一起来探索几款有用&#xff08;有趣&#xff09;的扩展插件。 1.…

NASA数据集—— 亚洲夏季季风化学和气候影响项目(ACCLIP)Roscoe 激光雷达收集的云和气溶胶ADO遥感数据

ACCLIP WB-57 Aerosol and Cloud Remotely Sensed Data 简介 ACCLIP_AerosolCloud_AircraftRemoteSensing_WB57_Data 是亚洲夏季季风化学和气候影响项目&#xff08;ACCLIP&#xff09;期间从 Roscoe 激光雷达收集的云和气溶胶遥感数据。该产品的数据收集工作已经完成。 亚洲…

【汇编】_Visual Studio2019写32位汇编

目录 第一步&#xff1a;创建新项目 1. 空项目—下一步 2. 选择位置—填写项目名—创建 第二步&#xff1a;项目生成依赖项 1. 右击项目名—生成依赖项—生成自定义 2. 选中masm—确定 第三步&#xff1a;创建源文件 1. 源文件—添加—新建项 2. 选择C文件—创建新文件…

ActiveMQ + MQTT 集群搭建(虚机版本) + Springboot使用配置

文章目录 前言一、ActiveMQ、 MQTT是什么&#xff1f;1.ActiveMQ介绍2.MQTT介绍 二、集群搭建步骤1.下载apache-activemq-5.15.12-bin.tar.gz2.上传apache-activemq-5.15.12-bin.tar.gz到服务器并解压文件到文件夹clusters、master、slave三个文件夹下面形成三个节点&#xff0…

配置QtCreator能加载自定义插件的环境

配置对应环境 引言查看当前版本配置能够加载插件的环境 引言 生成的自定义插件能在QtCreator的设计器中加载&#xff0c;需要满足当前使用的QtCreator的编译时所需的Qt库和编译器。 查看当前版本 这里需要先查看自己使用的QtCreator的版本&#xff0c;即生成QtCreator时使用…

17(18)-1-HTML5 新增语义标签及属性

个人主页&#xff1a;学习前端的小z 个人专栏&#xff1a;HTML5和CSS3悦读 本专栏旨在分享记录每日学习的前端知识和学习笔记的归纳总结&#xff0c;欢迎大家在评论区交流讨论&#xff01; 文章目录 ✍HTML5 新增语义标签及属性&#x1f48e;1 HTML5 新增的块级语义化标签&…

C语言——指针的高级引用

目录 1.概述 2.虚拟内存空间 2.1存储期限 2.2栈区管理 2.3堆区域的使用 3.动态内存分配和释放&#xff08;重点&#xff09; 3.1通用指针类型void 3.2内存分配malloc函数 3.2.1 malloc函数&#xff08;memory allocation&#xff09;&#xff08;注意len*size&#xff…

SAP SD学习笔记04 - 出荷Plant(交货工厂),出荷Point(装运点),输送计划,品目的可用性检查,一括纳入/分割纳入,仓库管理

上一章讲了SD的主数据。 SAP SD学习笔记03 - SD模块中的主数据-CSDN博客 本章讲出荷Plant&#xff08;交货工厂&#xff09;&#xff0c;出荷Point&#xff08;装运点&#xff09;和出和路线。 还是偏理论多一些&#xff0c;后面的文章尽量多加些练习巩固一下。 1&#xff0…

Element-UI plus 自定义-下拉框选择年份【vue3】

1.实现效果 2.实现代码展示 <template><el-select v-model"selectedYear" placeholder"请选择"><el-optionv-for"year in yearOptions":key"year":label"year":value"year"></el-option>…

实验四:基于内容的推荐

代码 import pandas as pd from sklearn.feature_extraction.text import TfidfVectorizer from sklearn.metrics.pairwise import cosine_similarity from sklearn.metrics.pairwise import pairwise_distances import numpy as np news_dfpd.read_csv(C:/Users/Administrat…