SpringBoot【开发实用篇】---- 整合第三方技术(监控)

news2024/10/6 22:30:42

SpringBoot【开发实用篇】---- 整合第三方技术(监控)

  • 1. 监控的意义
  • 2. 可视化监控平台
  • 3. 监控原理

在说监控之前,需要回顾一下软件业的发展史。最早的软件完成一些非常简单的功能,代码不多,错误也少。随着软件功能的逐步完善,软件的功能变得越来越复杂,功能不能得到有效的保障,这个阶段出现了针对软件功能的检测,也就是软件测试。伴随着计算机操作系统的逐步升级,软件的运行状态也变得开始让人捉摸不透,出现了不稳定的状况。伴随着计算机网络的发展,程序也从单机状态切换成基于计算机网络的程序,应用于网络的程序开始出现,由于网络的不稳定性,程序的运行状态让使用者更加堪忧。互联网的出现彻底打破了软件的思维模式,随之而来的互联网软件就更加凸显出应对各种各样复杂的网络情况之下的弱小。计算机软件的运行状况已经成为了软件运行的一个大话题,针对软件的运行状况就出现了全新的思维,建立起了初代的软件运行状态监控。

什么是监控?就是通过软件的方式展示另一个软件的运行情况,运行的情况则通过各种各样的指标数据反馈给监控人员。例如网络是否顺畅、服务器是否在运行、程序的功能是否能够整百分百运行成功,内存是否够用,等等等等。

1. 监控的意义

对于现代的互联网程序来说,规模越来越大,功能越来越复杂,还要追求更好的客户体验,因此要监控的信息量也就比较大了。由于现在的互联网程序大部分都是基于微服务的程序,一个程序的运行需要若干个服务来保障,因此第一个要监控的指标就是服务是否正常运行,也就是监控服务状态是否处理宕机状态。一旦发现某个服务宕机了,必须马上给出对应的解决方案,避免整体应用功能受影响。其次,由于互联网程序服务的客户量是巨大的,当客户的请求在短时间内集中达到服务器后,就会出现各种程序运行指标的波动。比如内存占用严重,请求无法及时响应处理等,这就是第二个要监控的重要指标,监控服务运行指标。虽然软件是对外提供用户的访问需求,完成对应功能的,但是后台的运行是否平稳,是否出现了不影响客户使用的功能隐患,这些也是要密切监控的,此时就需要在不停机的情况下,监控系统运行情况,日志是一个不错的手段。如果在众多日志中找到开发者或运维人员所关注的日志信息,简单快速有效的过滤出要看的日志也是监控系统需要考虑的问题,这就是第三个要监控的指标,监控程序运行日志。虽然我们期望程序一直平稳运行,但是由于突发情况的出现,例如服务器被攻击、服务器内存溢出等情况造成了服务器宕机,此时当前服务不能满足使用需要,就要将其重启甚至关闭,如果快速控制服务器的启停也是程序运行过程中不可回避的问题,这就是第四个监控项,管理服务状态。以上这些仅仅是从大的方面来思考监控这个问题,还有很多的细节点,例如上线了一个新功能,定时提醒用户续费,这种功能不是上线后马上就运行的,但是当前功能是否真的启动,如果快速的查询到这个功能已经开启,这也是监控中要解决的问题,等等。看来监控真的是一项非常重要的工作。

通过上述描述,可以看出监控很重要。那具体的监控要如何开展呢?还要从实际的程序运行角度出发。比如现在有3个服务支撑着一个程序的运行,每个服务都有自己的运行状态。

在这里插入图片描述
此时被监控的信息就要在三个不同的程序中去查询并展示,但是三个服务是服务于一个程序的运行的,如果不能合并到一个平台上展示,监控工作量巨大,而且信息对称性差,要不停的在三个监控端查看数据。如果将业务放大成30个,300个,3000个呢?看来必须有一个单独的平台,将多个被监控的服务对应的监控指标信息汇总在一起,这样更利于监控工作的开展。
在这里插入图片描述
新的程序专门用来监控,新的问题就出现了,是被监控程序主动上报信息还是监控程序主动获取信息?如果监控程序不能主动获取信息,这就意味着监控程序有可能看到的是很久之前被监控程序上报的信息,万一被监控程序宕机了,监控程序就无法区分究竟是好久没法信息了,还是已经下线了。所以监控程序必须具有主动发起请求获取被监控服务信息的能力。
在这里插入图片描述
如果监控程序要监控服务时,主动获取对方的信息。那监控程序如何知道哪些程序被自己监控呢?不可能在监控程序中设置我监控谁,这样互联网上的所有程序岂不是都可以被监控到,这样的话信息安全将无法得到保障。合理的做法只能是在被监控程序启动时上报监控程序,告诉监控程序你可以监控我了。看来需要在被监控程序端做主动上报的操作,这就要求被监控程序中配置对应的监控程序是谁。
在这里插入图片描述
被监控程序可以提供各种各样的指标数据给监控程序看,但是每一个指标都代表着公司的机密信息,并不是所有的指标都可以给任何人看的,乃至运维人员,所以对被监控指标的是否开放出来给监控系统看,也需要做详细的设定。

以上描述的整个过程就是一个监控系统的基本流程。

2. 可视化监控平台

springboot抽取了大部分监控系统的常用指标,提出了监控的总思想。然后就有好心的同志根据监控的总思想,制作了一个通用性很强的监控系统,因为是基于springboot监控的核心思想制作的,所以这个程序被命名为Spring Boot Admin

Spring Boot Admin,这是一个开源社区项目,用于管理和监控SpringBoot应用程序。这个项目中包含有客户端和服务端两部分,而监控平台指的就是服务端。我们做的程序如果需要被监控,将我们做的程序制作成客户端,然后配置服务端地址后,服务端就可以通过HTTP请求的方式从客户端获取对应的信息,并通过UI界面展示对应信息。

下面就来开发这套监控程序,先制作服务端,其实服务端可以理解为是一个web程序,收到一些信息后展示这些信息。

服务端开发
步骤①:导入springboot admin对应的starter,版本与当前使用的springboot版本保持一致,并将其配置成web工程

<dependency>
    <groupId>de.codecentric</groupId>
    <artifactId>spring-boot-admin-starter-server</artifactId>
    <version>2.5.4</version>
</dependency>

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

上述过程可以通过创建项目时使用勾选的形式完成。
在这里插入图片描述

步骤②:在引导类上添加注解@EnableAdminServer,声明当前应用启动后作为SpringBootAdmin的服务器使用

@SpringBootApplication
@EnableAdminServer
public class Springboot25AdminServerApplication {
    public static void main(String[] args) {
        SpringApplication.run(Springboot25AdminServerApplication.class, args);
    }
}

做到这里,这个服务器就开发好了,启动后就可以访问当前程序了,界面如下。

localhost

在这里插入图片描述
由于目前没有启动任何被监控的程序,所以里面什么信息都没有。下面制作一个被监控的客户端程序。

客户端开发
客户端程序开发其实和服务端开发思路基本相似,多了一些配置而已。
步骤①:导入springboot admin对应的starter,版本与当前使用的springboot版本保持一致,并将其配置成web工程

<dependency>
    <groupId>de.codecentric</groupId>
    <artifactId>spring-boot-admin-starter-client</artifactId>
    <version>2.5.4</version>
</dependency>

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

上述过程也可以通过创建项目时使用勾选的形式完成,不过一定要小心,端口配置成不一样的,否则会冲突。

步骤②:设置当前客户端将信息上传到哪个服务器上,通过yml文件配置

spring:
  boot:
    admin:
      client:
        url: http://localhost:8080

做到这里,这个客户端就可以启动了。启动后再次访问服务端程序,界面如下。
在这里插入图片描述
可以看到,当前监控了1个程序,点击进去查看详细信息。
在这里插入图片描述
由于当前没有设置开放哪些信息给监控服务器,所以目前看不到什么有效的信息。下面需要做两组配置就可以看到信息了。

  1. 开放指定信息给服务器看

  2. 允许服务器以HTTP请求的方式获取对应的信息

配置如下:

server:
  port: 80
spring:
  boot:
    admin:
      client:
        url: http://localhost:8080
management:
  endpoint:
    health:
      show-details: always
  endpoints:
    web:
      exposure:
        include: "*"

上述配置对于初学者来说比较容易混淆。简单解释一下,到下一节再做具体的讲解。springbootadmin的客户端默认开放了13组信息给服务器,但是这些信息除了一个之外,其他的信息都不让通过HTTP请求查看。所以你看到的信息基本上就没什么内容了,只能看到一个内容,就是下面的健康信息。
在这里插入图片描述
但是即便如此我们看到健康信息中也没什么内容,原因在于健康信息中有一些信息描述了你当前应用使用了什么技术等信息,如果无脑的对外暴露功能会有安全隐患。通过配置就可以开放所有的健康信息明细查看了。

management:
  endpoint:
    health:
      show-details: always

健康明细信息如下:
在这里插入图片描述
目前除了健康信息,其他信息都查阅不了。原因在于其他12种信息是默认不提供给服务器通过HTTP请求查阅的,所以需要开启查阅的内容项,使用*表示查阅全部。记得带引号。

endpoints:
  web:
    exposure:
      include: "*"

配置后再刷新服务器页面,就可以看到所有的信息了。
在这里插入图片描述
以上界面中展示的信息量就非常大了,包含了13组信息,有性能指标监控,加载的bean列表,加载的系统属性,日志的显示控制等等。

配置多个客户端
可以通过配置客户端的方式在其他的springboot程序中添加客户端坐标,这样当前服务器就可以监控多个客户端程序了。每个客户端展示不同的监控信息。
在这里插入图片描述
进入监控面板,如果你加载的应用具有功能,在监控面板中可以看到3组信息展示的与之前加载的空工程不一样。

  • 类加载面板中可以查阅到开发者自定义的类,如左图
    在这里插入图片描述

  • 映射中可以查阅到当前应用配置的所有请求
    在这里插入图片描述

  • 性能指标中可以查阅当前应用独有的请求路径统计数据
    在这里插入图片描述

3. 监控原理

通过查阅监控中的映射指标,可以看到当前系统中可以运行的所有请求路径,其中大部分路径以/actuator开头
在这里插入图片描述
首先这些请求路径不是开发者自己编写的,其次这个路径代表什么含义呢?既然这个路径可以访问,就可以通过浏览器发送该请求看看究竟可以得到什么信息。
在这里插入图片描述
通过发送请求,可以得到一组json信息,如下

{
    "_links": {
        "self": {
            "href": "http://localhost:81/actuator",
            "templated": false
        },
        "beans": {
            "href": "http://localhost:81/actuator/beans",
            "templated": false
        },
        "caches-cache": {
            "href": "http://localhost:81/actuator/caches/{cache}",
            "templated": true
        },
        "caches": {
            "href": "http://localhost:81/actuator/caches",
            "templated": false
        },
        "health": {
            "href": "http://localhost:81/actuator/health",
            "templated": false
        },
        "health-path": {
            "href": "http://localhost:81/actuator/health/{*path}",
            "templated": true
        },
        "info": {
            "href": "http://localhost:81/actuator/info",
            "templated": false
        },
        "conditions": {
            "href": "http://localhost:81/actuator/conditions",
            "templated": false
        },
        "shutdown": {
            "href": "http://localhost:81/actuator/shutdown",
            "templated": false
        },
        "configprops": {
            "href": "http://localhost:81/actuator/configprops",
            "templated": false
        },
        "configprops-prefix": {
            "href": "http://localhost:81/actuator/configprops/{prefix}",
            "templated": true
        },
        "env": {
            "href": "http://localhost:81/actuator/env",
            "templated": false
        },
        "env-toMatch": {
            "href": "http://localhost:81/actuator/env/{toMatch}",
            "templated": true
        },
        "loggers": {
            "href": "http://localhost:81/actuator/loggers",
            "templated": false
        },
        "loggers-name": {
            "href": "http://localhost:81/actuator/loggers/{name}",
            "templated": true
        },
        "heapdump": {
            "href": "http://localhost:81/actuator/heapdump",
            "templated": false
        },
        "threaddump": {
            "href": "http://localhost:81/actuator/threaddump",
            "templated": false
        },
        "metrics-requiredMetricName": {
            "href": "http://localhost:81/actuator/metrics/{requiredMetricName}",
            "templated": true
        },
        "metrics": {
            "href": "http://localhost:81/actuator/metrics",
            "templated": false
        },
        "scheduledtasks": {
            "href": "http://localhost:81/actuator/scheduledtasks",
            "templated": false
        },
        "mappings": {
            "href": "http://localhost:81/actuator/mappings",
            "templated": false
        }
    }
}

其中每一组数据都有一个请求路径,而在这里请求路径中有之前看到过的health,发送此请求又得到了一组信息

{
    "status": "UP",
    "components": {
        "diskSpace": {
            "status": "UP",
            "details": {
                "total": 297042808832,
                "free": 72284409856,
                "threshold": 10485760,
                "exists": true
            }
        },
        "ping": {
            "status": "UP"
        }
    }
}

当前信息与监控面板中的数据存在着对应关系
在这里插入图片描述
原来监控中显示的信息实际上是通过发送请求后得到json数据,然后展示出来。按照上述操作,可以发送更多的以/actuator开头的链接地址,获取更多的数据,这些数据汇总到一起组成了监控平台显示的所有数据。

到这里我们得到了一个核心信息,监控平台中显示的信息实际上是通过对被监控的应用发送请求得到的。那这些请求谁开发的呢?打开被监控应用的pom文件,其中导入了springboot admin的对应的client,在这个资源中导入了一个名称叫做actuator的包。被监控的应用之所以可以对外提供上述请求路径,就是因为添加了这个包。
在这里插入图片描述
Actuator,可以称为端点,描述了一组监控信息,SpringBootAdmin提供了多个内置端点,通过访问端点就可以获取对应的监控信息,也可以根据需要自定义端点信息。通过发送请求路劲**/actuator可以访问应用所有端点信息,如果端点中还有明细信息可以发送请求/actuator/端点名称**来获取详细信息。以下列出了所有端点信息说明:

ID描述默认启用
auditevents暴露当前应用程序的审计事件信息。
beans显示应用程序中所有 Spring bean 的完整列表。
caches暴露可用的缓存。
conditions显示在配置和自动配置类上评估的条件以及它们匹配或不匹配的原因。
configprops显示所有 @ConfigurationProperties 的校对清单。
env暴露 Spring ConfigurableEnvironment 中的属性。
flyway显示已应用的 Flyway 数据库迁移。
health显示应用程序健康信息
httptrace显示 HTTP 追踪信息(默认情况下,最后 100 个 HTTP 请求/响应交换)。
info显示应用程序信息。
integrationgraph显示 Spring Integration 图。
loggers显示和修改应用程序中日志记录器的配置。
liquibase显示已应用的 Liquibase 数据库迁移。
metrics显示当前应用程序的指标度量信息。
mappings显示所有 @RequestMapping 路径的整理清单。
scheduledtasks显示应用程序中的调度任务。
sessions允许从 Spring Session 支持的会话存储中检索和删除用户会话。当使用 Spring Session 的响应式 Web 应用程序支持时不可用。
shutdown正常关闭应用程序。
threaddump执行线程 dump。
heapdump返回一个 hprof 堆 dump 文件。
jolokia通过 HTTP 暴露 JMX bean(当 Jolokia 在 classpath 上时,不适用于 WebFlux)。
logfile返回日志文件的内容(如果已设置 logging.file 或 logging.path 属性)。支持使用 HTTP Range 头来检索部分日志文件的内容。
prometheus以可以由 Prometheus 服务器抓取的格式暴露指标。

上述端点每一项代表被监控的指标,如果对外开放则监控平台可以查询到对应的端点信息,如果未开放则无法查询对应的端点信息。通过配置可以设置端点是否对外开放功能。使用enable属性控制端点是否对外开放。其中health端点为默认端点,不能关闭。

management:
  endpoint:
    health:						# 端点名称
      show-details: always
    info:						# 端点名称
      enabled: true				# 是否开放

为了方便开发者快速配置端点,springboot admin设置了13个较为常用的端点作为默认开放的端点,如果需要控制默认开放的端点的开放状态,可以通过配置设置,如下:

management:
  endpoints:
    enabled-by-default: true	# 是否开启默认端点,默认值true

上述端点开启后,就可以通过端点对应的路径查看对应的信息了。但是此时还不能通过HTTP请求查询此信息,还需要开启通过HTTP请求查询的端点名称,使用“*”可以简化配置成开放所有端点的WEB端HTTP请求权限。

management:
  endpoints:
    web:
      exposure:
        include: "*"

整体上来说,对于端点的配置有两组信息,一组是endpoints开头的,对所有端点进行配置,一组是endpoint开头的,对具体端点进行配置。

management:
  endpoint:		# 具体端点的配置
    health:
      show-details: always
    info:
      enabled: true
  endpoints:	# 全部端点的配置
    web:
      exposure:
        include: "*"
    enabled-by-default: true

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

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

相关文章

在Window10和Window11系统,WPF使用Viewport3D 渲染失败问题解决方案

最近遇到个棘手的问题&#xff1a;在供应商提供的戴尔optiplex 3000的12代处理器主机的集成显卡Intel(R) UHD Graphics 770上使用Viewport3D 渲染失败&#xff08;3D模型显示不了&#xff0c;或者是显示不全&#xff09;&#xff0c;之前开发验证使用的是集成显卡Intel(R) UHD …

【FOSS】新一代绿色节能对象存储

01 背景概述 2020年9月中国明确了“碳达峰、碳中和”目标&#xff0c;2021年&#xff0c;碳达峰、碳中和被首次写入政府工作报告。该事件标志着中国对促进经济高质量发展&#xff0c;社会繁荣和生态环境保护的决心。 据IDC白皮书预测&#xff0c;中国将在2025年成为全球最大数…

团队数千人,苹果XR头显核心高管大曝光

上周&#xff0c;彭博社Mark Gurman从参与研发的相关人士了解到的消息&#xff0c;阐述了苹果XR头显开发简史。本周&#xff0c;继续公布了参与到苹果XR头显研发工作的一些关键岗位或高管人士。相关阅读&#xff1a;《苹果XR头显简史&#xff1a;现实困境与未来预期》 Mark Gu…

Flutter Overlay 你用上了么

Flutter Overlay 你用上了么 前言 Flutter中的Overlay是一个用于在屏幕上显示浮层的组件。它可以用来在应用程序中创建弹出窗口、提示框、菜单、对话框等等。 Overlay通常用于在用户与应用程序交互时显示临时性的UI元素&#xff0c;例如&#xff1a;用户点击按钮时显示下拉菜单…

3dMax一键窗户可入库插件使用方法详解

3dMax一键窗户(可入库)插件使用教程 3dMax一键窗户(可入库)插件,支持在选中的多边形上创建窗户模型,并可以自定义窗户形状,保存到库里下次使用。 【安装方法】 1.复制“窗户样本”文件夹到D盘根目录(D:\窗户样本) 2.拖动插件脚本到3dmax视口中打开即可。 【创建窗户】…

SolidWorks装配体中让弹簧随装配体运动的方法

弹簧是我们日常设计中最常用的几种零部件之一&#xff0c;但是弹簧不跟螺栓一样装好之后是相对静止的&#xff0c;弹簧在装配好后需要进行运动&#xff0c;在SolidWorks装配体中可以让弹簧跟随其他物体运动&#xff0c;操作分为三大步&#xff1a; 一、创建弹簧&#xff08;使…

微服务: Seata AT 分布式事务配置出现异常解决(相当全面)(下篇)

目录 1. 文章传送门 -> 上篇传送门: 微服务: Seata AT 分布式事务以及配置方式(上篇) -> 中篇传送门: 微服务: Seata AT springCloud整合分布式事务以配置方式(中篇) 2. 异常总结分类: 3. 解决上述问题: -> 解决上述问题一: 1. no available service null f…

面了一个测试工程师要求月薪23K,总感觉他藏了很多面试题...

最近有朋友去华为面试&#xff0c;面试前后进行了20天左右&#xff0c;包含4轮电话面试、1轮笔试、1轮主管视频面试、1轮hr视频面试。 据他所说&#xff0c;80%的人都会栽在第一轮面试&#xff0c;要不是他面试前做足准备&#xff0c;估计都坚持不完后面几轮面试。 其实&…

七人拼团系统开发模式,如何做到短短几个月就销售额上亿?

随着经济的迅速发展&#xff0c;市场上的商业模式也是层出不穷&#xff0c;而且各具特色&#xff0c;看得人眼花缭乱。最近又新出了一个七人拼团商业模式&#xff0c;不仅能够助力企业快速裂变获客&#xff0c;还能迅速提升产品销量&#xff0c;达到短短几个月就销售额上亿的“…

MariaDB 主从同步配置

1 服务器结构 角色ip地址安装教程主节点192.168.31.102CentOS-7 安装 MariaDB-10.8从节点192.168.31.103 2 原理&#xff1a; 原理&#xff1a; &#xff08;1&#xff09;master服务器将数据的改变记录到二进制binlog日志&#xff0c;当master上的数据发生改变时&#xff0c…

【连续介质力学】张量场

张量场 张量场表示张量 T ( x ⃗ , t ) T(\vec x, t) T(x ,t)在空间 x ⃗ \vec x x 和时间 t t t中如何变化&#xff0c;将张量场视为可微函数 如果一个张量场不依赖于时间&#xff0c;则此张量场称为定常场&#xff0c;例如 T T ( x ⃗ ) T T(\vec x) TT(x )&#xff1b;相…

如此优秀的低代码平台,佬们一起来体验一把!

前言&#xff1a;低代码平台是一种新兴的应用开发技术&#xff0c;将可视化建模、自动生成代码和开发者编写的代码结合在一起&#xff0c;使应用程序的开发变得更加快速、简单且高效。低代码平台的基本思想是通过消除繁琐的手动编码工作&#xff0c;来让开发者更好地专注于业务…

基于 Spring Boot + MyBatis Plus + Vue Element 实现的后台管理系统 + 微信小程序

管理后台的 Vue3 版本采用 vue-element-plus-admin &#xff0c;Vue2 版本采用 vue-element-admin 管理后台的移动端采用 uni-app 方案&#xff0c;一份代码多终端适配&#xff0c;同时支持 APP、小程序、H5&#xff01; 后端采用 Spring Boot、MySQL MyBatis Plus、Redis …

UnityVR--组件3--Line Renderer--线性渲染

目录 前言 Line Renderer组件介绍 Trail Renderer组件介绍 使用Line Renderer绘制线段 使用系统工具或自定义工具绘制线段 Trail Renderer简单制作子弹拖尾效果 前言 Line Renderer线性渲染组件用于在3D中渲染线段&#xff0c;如之前在小游戏中做过的激光门伤害&#xff0…

Axure设计—动态条形图(中继器)

本文将教大家如何用AXURE中的中继器动态条形图。 一、效果介绍 如图&#xff1a; 预览地址&#xff1a;https://i7x7i9.axshare.com 下载地址&#xff1a;https://download.csdn.net/download/weixin_43516258/87807039?spm1001.2014.3001.5503 二、功能介绍 简单填写中继…

PyQt5桌面应用开发(17):类结构+QWebEngineView

本文目录 PyQt5桌面应用系列PyQt5学习PyQt5类结构和帮助速查实现与解释最终界面和完整源代码界面完整的代码 总结 PyQt5桌面应用系列 PyQt5桌面应用开发&#xff08;1&#xff09;&#xff1a;需求分析 PyQt5桌面应用开发&#xff08;2&#xff09;&#xff1a;事件循环 PyQt5桌…

Spring 如何处理请求参数和表单数据

当我们开发 Web 应用程序时&#xff0c;处理请求参数和表单数据是必不可少的。Spring MVC 是一个流行的 Java Web 框架&#xff0c;提供了多种方式来处理请求参数和表单数据。本文将介绍 Spring MVC 中处理请求参数和表单数据的常用方式&#xff0c;并提供相应的代码示例。 处…

Redis数据结构-SDS

一、SDS&#xff08;Simple Dynamic String&#xff0c;简单动态字符串&#xff09; Redis没有使用C语言传统的字符串表示方式&#xff08;以’\0’结尾的字符数组&#xff09;&#xff0c;而是自己实现了sds的抽象类型&#xff0c;Redis默认使用sds作为字符串的表示。 set ms…

新视野(2023.5.5-2023.5.12)

一、知识&#xff1a; 媒体账号买卖网站 A5新媒体交易&#xff1a;https://xmt.a5.net/ 新媒虎:https://www.xinmeihu.com/ 二、资讯&#xff1a; GPT最大的竞争对手Claude宣布支持100K的上下文&#xff01;基本上一本中篇小说都能塞进去了&#xff0c;你再不需要ChatPDF这种…

【框架源码】手写Spring框架IOC容器核心流程

要是想要了解Spring IOC底层&#xff0c;首先我们就得先了解什么是IOC。 IOC就是控制反转&#xff0c;把对象创建和对象之间的调用过程交给Spring进行管理。 使用IOC目的就是之前我们创建对象的方式都是用new的方式创建&#xff0c;这个方式有个缺点&#xff0c;被创建对象的…