.NET IoC 容器(三)Autofac

目录

  • .NET IoC 容器(三)Autofac
    • Autofac
    • Nuget 安装
    • 实现DI
      • 定义接口
      • 定义实现类
      • 依赖注入
    • 注入方式
      • 构造函数注入 | 属性注入 | 方法注入
      • 注入实现
    • 接口注册
      • 重复注册
      • 指定参数注册
    • 生命周期
      • 默认生命周期
      • 单例生命周期
      • 每个周期范围一个生命周期
    • 依赖配置
      • Nuget
      • 配置文件
    • AOP
      • Nuget安装
      • 定义接口、实现类
      • 定义切面
      • 容器配置
    • 参考资料

.NET IoC 容器(三)Autofac

Autofac

Autofac 是一个用于 .NET 应用程序的依赖注入 (Dependency Injection, DI) 容器。它帮助开发人员管理对象的创建和生命周期,使得依赖项的注入更加灵活和可维护。以下是 Autofac 的主要功能和特性概述:

依赖注入 (Dependency Injection)

Autofac 允许你通过构造函数、属性或方法注入依赖项。这样,你可以轻松地将对象的依赖关系传递给需要它们的类,从而提高代码的可测试性和可维护性。

模块化设计 (Modular Design)

Autofac 支持模块化设计,可以将相关的依赖项注册逻辑分组到模块中。这使得大型应用程序的配置更加简洁和易于管理。

生命周期管理 (Lifecycle Management)

Autofac 提供多种对象生命周期管理方式,例如单例 (Singleton)、每次请求 (Instance Per Dependency)、每个生命周期范围 (Instance Per Lifetime Scope) 等,允许你精确控制对象的创建和销毁时机。

注册与解析 (Registration and Resolution)

Autofac 通过流畅的 API 提供了多种注册组件的方式。你可以注册类型、实例、工厂方法,甚至通过扫描程序集自动注册组件。此外,Autofac 的解析功能支持构造函数参数注入、命名参数注入等高级特性。

支持 AOP (Aspect-Oriented Programming)

Autofac 与 AOP 框架(如 Castle Windsor)集成,支持横切关注点(如日志记录、事务管理)的处理,从而使业务逻辑代码更加简洁。

集成支持

Autofac 与许多流行的 .NET 库和框架集成良好,包括 ASP.NET Core、WCF、Web API、MVC 等。通过这些集成,Autofac 可以轻松地管理 web 应用程序中的依赖项。

扩展性

Autofac 具有很高的扩展性,可以通过自定义注册源、生命周期、解析器等方式扩展其功能,以满足特定应用的需求。

Nuget 安装

在这里插入图片描述

实现DI

定义接口

internal interface IComputer
{
}
internal interface IKeyboard
{
}
internal interface IMouse
{
}
internal interface IPerson
{
    IComputer Computer { get; set; }
    IKeyboard Keyboard { get; set; }
    IMouse Mouse { get; set; }
    void Work();
}

定义实现类

internal class ConstructBase
{
    public ConstructBase() 
    {
        Console.WriteLine($"{this.GetType().Name} - 被构造了");
    }
}
internal class LenovoComputer : ConstructBase, IComputer
{
    public LenovoComputer() : base() { }
}
internal class TogarKeyboard : ConstructBase, IKeyboard
{
    public TogarKeyboard() : base() { }
}
internal class LogitechMouse : ConstructBase, IMouse
{
    public LogitechMouse() : base() { }
}
internal class Programmer : ConstructBase, IPerson
{
    public IComputer Computer { get; set; }
    public IKeyboard Keyboard { get; set; }
    public IMouse Mouse { get; set; }

    public Programmer(IComputer computer, IKeyboard keyboard, IMouse mouse) : base()
    {
        Computer = computer;
        Keyboard = keyboard;
        Mouse = mouse;
    }

    public void Work()
    {
        Console.WriteLine("Programmers are building software...");
    }
}

依赖注入

var builder = new ContainerBuilder();
builder.RegisterType<LenovoComputer>().As<IComputer>();
builder.RegisterType<TogarKeyboard>().As<IKeyboard>();
builder.RegisterType<LogitechMouse>().As<IMouse>();
builder.RegisterType<Programmer>().As<IPerson>();
var container = builder.Build();
IPerson programmer = container.Resolve<IPerson>();
programmer.Work();

输出

Zhy.IoC.Autofac.LenovoComputer - 被构造了
Zhy.IoC.Autofac.TogarKeyboard - 被构造了
Zhy.IoC.Autofac.LogitechMouse - 被构造了
Zhy.IoC.Autofac.Programmer - 被构造了
Programmers are building software...

注入方式

构造函数注入 | 属性注入 | 方法注入

定义特性用来筛选属性注入

public class InjectPropertyAttribute : Attribute
{

}

定义实现类

public class Gamer : ConstructBase, IPerson
{
    public IComputer Computer { get; set; }
    [InjectProperty]
    public IKeyboard Keyboard { get; set; }
    public IMouse Mouse { get; set; }

    public Gamer(IComputer computer) : base()
    {
        Computer = computer;
    }

    public void Inject(IMouse mouse)
    {
        Mouse = mouse;
    }

    public void Work()
    {
        Console.WriteLine("The player is playing...");
    }
}

注入实现

// 注入顺序(与编码顺序无关):构造函数注入 > 属性注入 > 方法注入
var builder = new ContainerBuilder();
builder.RegisterType<LenovoComputer>().As<IComputer>();
builder.RegisterType<TogarKeyboard>().As<IKeyboard>();
builder.RegisterType<LogitechMouse>().As<IMouse>();
builder.RegisterType<Gamer>()
    // 方法注入
    .OnActivating(e =>
    {
        IMouse mouse = e.Context.Resolve<IMouse>();
        e.Instance.Inject(mouse);
    })
    // 属性注入
    .PropertiesAutowired((g, o) => g.Name == "Keyboard")
    // 构造函数注入
    .UsingConstructor(typeof(IComputer))
    .As<IPerson>();
var container = builder.Build();
IPerson gamer = container.Resolve<IPerson>();
gamer.Work();

输出

Zhy.IoC.Autofac.LenovoComputer - 被构造了
Zhy.IoC.Autofac.Gamer - 被构造了
Zhy.IoC.Autofac.TogarKeyboard - 被构造了
Zhy.IoC.Autofac.LogitechMouse - 被构造了
The player is playing...

结果

注入顺序:构造函数注入 > 属性注入 > 方法注入

接口注册

重复注册

var builder = new ContainerBuilder();
builder.RegisterType<LenovoComputer>().As<IComputer>();
builder.RegisterType<TogarKeyboard>().As<IKeyboard>();
builder.RegisterType<LogitechMouse>().As<IMouse>();
builder.RegisterType<Programmer>().As<IPerson>();
builder.RegisterType<Gamer>()
    // 方法注入
    .OnActivating(e =>
    {
        IMouse mouse = e.Context.Resolve<IMouse>();
        e.Instance.Inject(mouse);
    })
    // 属性注入
    .PropertiesAutowired((g, o) => g.Name == "Keyboard")
    // 构造函数注入
    .UsingConstructor(typeof(IComputer))
    .As<IPerson>();
var container = builder.Build();
IPerson programmer = container.Resolve<IPerson>();
programmer.Work();

输出

Zhy.IoC.Autofac.LenovoComputer - 被构造了
Zhy.IoC.Autofac.Gamer - 被构造了
Zhy.IoC.Autofac.TogarKeyboard - 被构造了
Zhy.IoC.Autofac.LogitechMouse - 被构造了
The player is playing...

调换Gamer和Programmer的注册顺序:

var builder = new ContainerBuilder();
builder.RegisterType<LenovoComputer>().As<IComputer>();
builder.RegisterType<TogarKeyboard>().As<IKeyboard>();
builder.RegisterType<LogitechMouse>().As<IMouse>();
builder.RegisterType<Gamer>()
    // 方法注入
    .OnActivating(e =>
    {
        IMouse mouse = e.Context.Resolve<IMouse>();
        e.Instance.Inject(mouse);
    })
    // 属性注入
    .PropertiesAutowired((g, o) => g.Name == "Keyboard")
    // 构造函数注入
    .UsingConstructor(typeof(IComputer))
    .As<IPerson>();
builder.RegisterType<Programmer>().As<IPerson>();
var container = builder.Build();
IPerson programmer = container.Resolve<IPerson>();
programmer.Work();

输出

Zhy.IoC.Autofac.LenovoComputer - 被构造了
Zhy.IoC.Autofac.TogarKeyboard - 被构造了
Zhy.IoC.Autofac.LogitechMouse - 被构造了
Zhy.IoC.Autofac.Programmer - 被构造了
Programmers are building software...

结论

同一接口多次注册时,后注册的会覆盖前面注册的,若需要实现多重注册,需要指定名称

var builder = new ContainerBuilder();
builder.RegisterType<LenovoComputer>().As<IComputer>();
builder.RegisterType<TogarKeyboard>().As<IKeyboard>();
builder.RegisterType<LogitechMouse>().As<IMouse>();
builder.RegisterType<Gamer>()
    // 方法注入
    .OnActivating(e =>
    {
        IMouse mouse = e.Context.Resolve<IMouse>();
        e.Instance.Inject(mouse);
    })
    // 属性注入
    .PropertiesAutowired((g, o) => g.Name == "Keyboard")
    // 构造函数注入
    .UsingConstructor(typeof(IComputer))
    .Named<IPerson>("person");
builder.RegisterType<Programmer>().Named<IPerson>("programmer");
var container = builder.Build();
IPerson programmer = container.ResolveNamed<IPerson>("programmer");
IPerson person = container.ResolveNamed<IPerson>("person");
programmer.Work();
person.Work();

输出

Zhy.IoC.Autofac.LenovoComputer - 被构造了
Zhy.IoC.Autofac.TogarKeyboard - 被构造了
Zhy.IoC.Autofac.LogitechMouse - 被构造了
Zhy.IoC.Autofac.Programmer - 被构造了
Zhy.IoC.Autofac.LenovoComputer - 被构造了
Zhy.IoC.Autofac.Gamer - 被构造了
Zhy.IoC.Autofac.TogarKeyboard - 被构造了
Zhy.IoC.Autofac.LogitechMouse - 被构造了
Programmers are building software...
The player is playing...

指定参数注册

修改接口

internal interface IMouse
{
    string Type { get; set; }
}

修改实现类

internal class LogitechMouse : ConstructBase, IMouse
{
    public LogitechMouse() : base() { }

    public LogitechMouse(string type) : base()
    {
        Type = type;
    }

    public string Type { get; set; }
}

注入

var builder = new ContainerBuilder();
builder.RegisterType<LogitechMouse>().WithParameter("type","502").As<IMouse>();
var container = builder.Build();
IMouse mouse = container.Resolve<IMouse>();
Console.WriteLine("mouse type: " + mouse.Type);

输出

Zhy.IoC.Autofac.LogitechMouse - 被构造了
mouse type: 502

生命周期

Instance Per Dependency(默认) 每次请求组件时都会创建一个新的实例。这是默认的生命周期管理模式。

builder.RegisterType<MyService>().As<IMyService>();

Singleton 在整个容器生命周期内,只有一个实例。

builder.RegisterType<MyService>().As<IMyService>().SingleInstance();

Instance Per Lifetime Scope 在每个生命周期范围内,共享一个实例。每个生命周期范围都会创建一个新的实例,但在该范围内共享该实例。

builder.RegisterType<MyService>().As<IMyService>().InstancePerLifetimeScope();

Instance Per Matching Lifetime Scope 在特定的生命周期范围内共享实例,需要指定标记。

builder.RegisterType<MyService>().As<IMyService>().InstancePerMatchingLifetimeScope("my-scope");

Instance Per Request 通常用于 web 应用程序,在每个 HTTP 请求期间共享一个实例。

builder.RegisterType<MyService>().As<IMyService>().InstancePerRequest();

Externally Owned 组件由外部代码管理生命周期,Autofac 不会在容器释放时释放该实例。

builder.RegisterType<MyService>().As<IMyService>().ExternallyOwned();

Instance Per Dependency 每次依赖请求时都会创建一个新实例。

builder.RegisterType<MyService>().As<IMyService>().InstancePerDependency();

默认生命周期

var builder = new ContainerBuilder();
builder.RegisterType<LenovoComputer>().As<IComputer>();
var container = builder.Build();
IComputer computer0 = container.Resolve<IComputer>();
IComputer computer1 = container.Resolve<IComputer>();
Console.WriteLine("computer0: " + computer0.GetHashCode());
Console.WriteLine("computer1: " + computer1.GetHashCode());
Console.WriteLine($"computer0 == computer1: {computer0 == computer1}");

输出

Zhy.IoC.Autofac.LenovoComputer - 被构造了
Zhy.IoC.Autofac.LenovoComputer - 被构造了
computer0: 32347029
computer1: 22687807
computer0 == computer1: False

单例生命周期

var builder = new ContainerBuilder();
builder.RegisterType<LenovoComputer>().As<IComputer>().SingleInstance();
var container = builder.Build();
IComputer computer0 = container.Resolve<IComputer>();
IComputer computer1 = container.Resolve<IComputer>();
Console.WriteLine("computer0: " + computer0.GetHashCode());
Console.WriteLine("computer1: " + computer1.GetHashCode());
Console.WriteLine($"computer0 == computer1: {computer0 == computer1}");

输出

Zhy.IoC.Autofac.LenovoComputer - 被构造了
computer0: 32347029
computer1: 32347029
computer0 == computer1: True

每个周期范围一个生命周期

var builder = new ContainerBuilder();
builder.RegisterType<LenovoComputer>().As<IComputer>().InstancePerLifetimeScope();
var container = builder.Build();
IComputer computer0 = container.Resolve<IComputer>();
using (var scope = container.BeginLifetimeScope())
{
    IComputer computer1 = scope.Resolve<IComputer>();
    IComputer computer2 = scope.Resolve<IComputer>();
    Console.WriteLine("computer0: " + computer0.GetHashCode());
    Console.WriteLine("computer1: " + computer1.GetHashCode());
    Console.WriteLine("computer2: " + computer2.GetHashCode());
    Console.WriteLine($"computer0 == computer1: {computer0 == computer1}");
    Console.WriteLine($"computer1 == computer2: {computer1 == computer2}");
}

输出

Zhy.IoC.Autofac.LenovoComputer - 被构造了
Zhy.IoC.Autofac.LenovoComputer - 被构造了
computer0: 32347029
computer1: 22687807
computer2: 22687807
computer0 == computer1: False
computer1 == computer2: True

依赖配置

Nuget

在这里插入图片描述

配置文件

Json

{
  "components": [
    {
      "type": "Zhy.IoC.Autofac.LenovoComputer,Zhy.IoC.Autofac",
      "services": [
        {
          "type": "Zhy.IoC.Core.IComputer,Zhy.IoC.Core"
        }
      ],
      "autoActivate": true,
      "instanceScope": "singleinstance"
    },
    {
      "type": "Zhy.IoC.Autofac.TogarKeyboard,Zhy.IoC.Autofac",
      "services": [
        {
          "type": "Zhy.IoC.Core.IKeyboard,Zhy.IoC.Core"
        }
      ],
      "autoActivate": true,
      "instanceScope": "singleinstance"
    },
    {
      "type": "Zhy.IoC.Autofac.LogitechMouse,Zhy.IoC.Autofac",
      "services": [
        {
          "type": "Zhy.IoC.Core.IMouse,Zhy.IoC.Core"
        }
      ],
      "parameters": {
        "places": 4
      },
      "autoActivate": true,
      "instanceScope": "singleinstance"
    },
    {
      "type": "Zhy.IoC.Autofac.Programmer,Zhy.IoC.Autofac",
      "services": [
        {
          "type": "Zhy.IoC.Core.IPerson,Zhy.IoC.Core"
        }
      ],
      "autoActivate": true,
      "instanceScope": "singleinstance"
    }
  ]
}

XML

<?xml version="1.0" encoding="utf-8" ?>
<autofac>
	<components name="0">
		<type>Zhy.IoC.Autofac.LenovoComputer,Zhy.IoC.Autofac</type>
		<services name="0" type="Zhy.IoC.Core.IComputer,Zhy.IoC.Core" />
	</components>
	<components name="1">
		<type>Zhy.IoC.Autofac.TogarKeyboard,Zhy.IoC.Autofac</type>
		<services name="0" type="Zhy.IoC.Core.IKeyboard,Zhy.IoC.Core" />
	</components>
	<components name="2">
		<type>Zhy.IoC.Autofac.LogitechMouse,Zhy.IoC.Autofac</type>
		<services name="0" type="Zhy.IoC.Core.IMouse,Zhy.IoC.Core" />
	</components>
	<components name="3">
		<type>Zhy.IoC.Autofac.Programmer,Zhy.IoC.Autofac</type>
		<services name="0" type="Zhy.IoC.Core.IPerson,Zhy.IoC.Core" />
	</components>
</autofac>

调用

var config = new ConfigurationBuilder();
config.AddJsonFile("DI-Autofac.json");
// config.AddXmlFile("DI-Autofac.xml");
var module = new ConfigurationModule(config.Build());
var builder = new ContainerBuilder();
builder.RegisterModule(module);
var container = builder.Build();
IPerson programmer = container.Resolve<IPerson>();
programmer.Work();

输出

Zhy.IoC.Autofac.LenovoComputer - 被构造了
Zhy.IoC.Autofac.TogarKeyboard - 被构造了
Zhy.IoC.Autofac.LogitechMouse - 被构造了
Zhy.IoC.Autofac.Programmer - 被构造了
Programmers are building software...

AOP

Nuget安装

在这里插入图片描述

定义接口、实现类

public interface IMyService
{
    void DoWork();
}
public void DoWork()
{
    Console.WriteLine("Doing work...");
}

定义切面

using Castle.DynamicProxy;

public class LoggingInterceptor : IInterceptor
{
    public void Intercept(IInvocation invocation)
    {
        Console.WriteLine($"Invoking method {invocation.Method.Name} at {DateTime.Now}");
        invocation.Proceed();
        Console.WriteLine($"Method {invocation.Method.Name} has completed at {DateTime.Now}");
    }
}

容器配置

var builder = new ContainerBuilder();
builder.Register(c => new LoggingInterceptor());
builder.RegisterType<MyService>()
       .As<IMyService>()
       .EnableInterfaceInterceptors()
       .InterceptedBy(typeof(LoggingInterceptor));
var container = builder.Build();
var service = container.Resolve<IMyService>();
service.DoWork();

输出

Invoking method DoWork at 2024/5/30 16:49:34
Doing work...
Method DoWork has completed at 2024/5/30 16:49:34

参考资料

IOC容器之Unity与AutoFac_unity autofac-CSDN博客

Autofac/src/Autofac at develop · autofac/Autofac (github.com)

控制容器的反转和依赖关系注入模式 (martinfowler.com)

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

AIGIS地图智能体功能预览——最强WebGIS打工人秒上岗

目录 前言1.这地图智能体是用来干什么的&#xff1f;2.智能体介绍3.二维效果4.三维效果5.大模型写不出来正确的代码怎么办&#xff1f;6.所以最终会产生一个什么样的现象&#xff1f;7.现在我们可用的大模型有哪些&#xff1f;8.不会写代码怎么开发自己的专属智能体&#xff1f…

处理无法拉取GitHub库的解决方案

提交和拉取github上的库总是失败&#xff0c;这里记录一下如何使用代理解决。 首先找到端口&#xff0c;记住它的端口 然后使用git命令 # HTTP/HTTPS 协议 git config ––global http.url.proxy http://127.0.0.1:port # 以 Github 为例 git config ––global http.https:/…

解决MyBatis的N+1问题

解决MyBatis的N1问题 N1问题通常出现在一对多关联查询中。当我们查询主表数据&#xff08;如订单&#xff09;并希望获取关联的从表数据&#xff08;如订单的商品&#xff09;时&#xff0c;如果每获取一条主表记录都要执行一次从表查询&#xff0c;就会产生N1次查询的问题。假…

线性电源运放驱动调整管的方案仿真

群里有人的电路板做出来电压不稳&#xff0c;加负载就掉电压。我对这个运放的工作状态不是很理解&#xff0c;所以仿真了一下。结果却是稳定的。他用12v给运放供电&#xff0c;要求输出10.5. 从仿真看。12运放供电只能输出9v。而且还是到了运放的极限。所以通过仿真后确定怀疑路…

10-Django项目--Ajax请求

目录 Ajax请求 简单示范 html 数据添加 py文件 html文件 demo_list.html Ajax_data.py 图例 Ajax请求 简单示范 html <input type"button" id"button-one" class"btn btn-success" value"点我"> ​ ​ <script>/…

实现秒传与限速!深度解析万亿GB网盘系统架构

1. 系统需求与挑战 1.1 DBox核心功能 在设计一个面向万亿GB的网盘系统时&#xff0c;我们需要首先明确系统的核心功能需求。DBox 作为一个高并发、高可靠的网盘系统&#xff0c;核心功能需求主要包括以下几点&#xff1a; 海量存储&#xff1a;支持存储海量数据&#xff0c;…

面粉厂/木材厂选择防爆客流统计系统的原因

在面粉厂和木材厂这样的特殊行业中&#xff0c;存在着一系列的痛点问题。 对于面粉厂而言&#xff0c;面粉粉尘的存在使其面临着爆炸的潜在危险&#xff0c;而人员的随意流动和不确切统计可能会进一步加剧安全风险。同时&#xff0c;难以精确掌握不同区域的人员分布情况&#x…

SploitScan:一款多功能实用型安全漏洞管理平台

关于SploitScan SploitScan是一款功能完善的实用型网络安全漏洞管理工具&#xff0c;该工具提供了用户友好的界面&#xff0c;旨在简化广大研究人员识别已知安全漏洞的相关信息和复现过程。 SploitScan可以帮助网络安全专业人员快速识别和测试已知安全漏洞&#xff0c;如果你需…

解线性方程组——最速下降法及图形化表示 | 北太天元 or matlab

文章所对应的视频讲解 最速下降法 解线性方程组 一、思路转变 A为对称正定矩阵&#xff0c; A x b Ax b Axb 求解向量 x x x这个问题可以转化为一个求 f ( x ) f(x) f(x)极小值点的问题&#xff0c;为什么可以这样&#xff1a; f ( x ) 1 2 x T A x − x T b c f(x) \f…

大数据数据治理

大数据数据治理介绍 大数据数据治理是一个复杂的过程&#xff0c;涉及到数据的标准化、融通、关联、解析、聚合等一系列活动。其核心目标是在确保数据安全的基础上&#xff0c;提高大数据资源和资产的可用性、易用性和可靠性&#xff0c;从而显著提升大数据资源和资产的价值7。…

从0开始学人工智能测试节选:Spark -- 结构化数据领域中测试人员的万金油技术(四)

上一章节我们了解了 shuffle 相关的概念和原理后其实可以发现一个问题&#xff0c;那就是 shuffle 比较容易造成数据倾斜的情况。 例如上一节我们看到的图&#xff0c;在这批数据中&#xff0c;hello 这个单词的行占据了绝大部分&#xff0c;当我们执行 groupByKey 的时候触发了…

FL Studio21.2.8中文版水果音乐制作的革新之旅!

在数字化浪潮的推动下&#xff0c;音乐制作领域经历了翻天覆地的变化。从最初的模拟技术到如今的全数字化处理&#xff0c;音乐制作的门槛被大幅降低&#xff0c;越来越多的音乐爱好者和专业人士开始尝试自行创作和编辑音乐。在这个过程中&#xff0c;各种专业音乐制作软件成为…

孵化器补贴政策提问模板

对于一些需要创业的人来说&#xff0c;找场地是非常非常难的&#xff0c;一个好的场地能够提高创业的成功率&#xff0c;下面这些内容对于孵化器产业园的政策有一个好的提问&#xff0c;可以帮助你们了解这个孵化器合不合适。需要创业的人可以收藏 某孵化器政策示例 提问模板 …

Java进制转换

进制介绍 二进制&#xff1a;0B开头&#xff0c;0-1 八进制&#xff1a;0开头&#xff0c;0-7 十进制&#xff1a;0-9 十六进制&#xff1a;0x开头&#xff0c;0-9和A-F public class Binary{public static void main(String[] args){//二进制 10int n10B1010//十进制 1010int…

短视频动画脚本:成都鼎茂宏升文化传媒公司

短视频动画脚本&#xff1a;创作与魅力的探索 在数字化时代的浪潮中&#xff0c;短视频动画以其独特的魅力迅速崛起&#xff0c;成为大众娱乐和信息传播的重要载体。成都鼎茂宏升文化传媒公司作为一名原创文章编辑&#xff0c;我深入探索了短视频动画脚本的创作过程&#xff0…

揭秘GPU技术新趋势:从虚拟化到池化

从GPU虚拟化到池化 大模型兴起加剧GPU算力需求&#xff0c;企业面临GPU资源有限且利用率不高的挑战。为打破这一瓶颈&#xff0c;实现GPU算力资源均衡与国产化替代&#xff0c;GPU算力池化成为关键。本文深入探讨GPU设备虚拟化途径、共享方案及云原生实现&#xff0c;旨在优化资…

大模型学习资料整理:如何从0到1学习大模型,搭建个人或企业RAG系统,如何评估与优化(更新中...)

通过本文您可以了解到&#xff1a; 学习&#xff1a;从小白如何入手&#xff0c;从0到1开始学习大模型。RAG系统&#xff1a;我想搭建属于自己或者企业的RAG系统&#xff0c;我该怎么去做&#xff1f;评估&#xff1a;微调后的模型或者RAG系统&#xff0c;如何评估自己的模型和…

软件质量保障——三、四

三、黑盒测试 1.黑盒测试概述 1.1 如何理解黑盒测试&#xff1f; 1.2 黑盒测试有什么特点&#xff1f; 1.3 如何实施黑盒测试&#xff1f; 2. 黑盒测试用例设计和生成方法&#xff08;这里还是要自己找题做&#xff09; 2.1 等价类划分法 步骤&#xff1a; 1.选择划分准…

设置电脑定时关机

1.使用快捷键winR 打开运行界面 2.输入cmd &#xff0c;点击确认&#xff0c;打开命令行窗口&#xff0c;输入 shutdown -s -t 100&#xff0c;回车执行命令&#xff0c;自动关机设置成功 shutdown: 这是主命令&#xff0c;用于执行关闭或重启操作。-s: 这个参数用于指定执行关…

flask音乐交流平台-计算机毕业设计源码57105

摘要 科技进步的飞速发展引起人们日常生活的巨大变化&#xff0c;电子信息技术的飞速发展使得电子信息技术的各个领域的应用水平得到普及和应用。信息时代的到来已成为不可阻挡的时尚潮流&#xff0c;人类发展的历史正进入一个新时代。在现实运用中&#xff0c;应用软件的工作规…