当前位置: 首页 > news >正文

Angular 2 学习笔记

Angular 2 应用主要由以下 几个部分组成:

1、模块 (Modules):
2、组件 (Components):
3、模板 (Templates)​​​​​​​:
4、元数据 (Metadata):
5、数据绑定 (Data Binding)
6、指令 (Directives)
7、服务 (Services):
8、依赖注入 (Dependency Injection)
9、路由(Route):建立URL路径和组件之间的对应关系,根据不同的URL路径匹配对应的组件并渲染。

一、元数据(Metadata)

元数据就是在定义模块、组件、服务的时候,Decorator(装饰器)方法里面的参数内容,例如一个AppComponent的元数据,就是 @Component​​ 里面的参数,如下:

{selector : 'mylist',template : '<h2>元数据</h2>'directives : [ComponentDetails]
}

在Angular2中,Decorator(装饰器)被大量使用,当我们定义模板、组件、服务、指令时,都是使用Decorator来定义。顾名思义,Decorator(装饰器)就是在一个类上面添加一些额外属性或方法

举个例子,根组件AppComponent,在定义它的时候,通过 ​​@Component​​ 才能把它定义成一个Angular的组件。然后我们在这个元数据里面,设置了这个组件对应的selector,模板和样式。

这样Angular框架在解析这个类的时候,就会按照组件的规则去解析并初始化。

当在一个页面里面遇到这个selector设置的标签时,就会初始化这个组件,渲染模板生成html显示到对应的标签里面,并应用样式。

二、模块 (Modules)

module是指使用@NgModule修饰的class。

@NgModule利用一个元数据对象来告诉Angular如何去编译和运行代码。

可以将组件、服务、指令、方法、管道等封装成一个模块,并且可以将它们的访问权限声明为公有,以便外部模块的组件可以访问和使用到它们。

内置模块

Angular2将许多常用功能分配到一个个的模块中:

  • ApplicationModule:封装一些启动相关的工具
  • CommonModule:封装一些常用的内置指令和内置管道等
  • BrowserModule:封装在浏览器平台运行时的一些工具库,同时将CommonModule和ApplicationModule打包导出,所以通常在使用时引入BrowserModule就可以了
  • FormsModule和ReactiveFormsModule:封装表单相关的组件指令等
  • RouterModule:封装路由相关的组件指令等
  • HttpModule:封装网络请求相关的服务等

在使用前,需导入相关模块包:

  • @angular/core:存放核心代码,如变化监测机制、依赖注入机制、渲染等,核心功能的实现、装饰器(@Component、@Directive等)也会存放到这个模块。
  • @angular/common:存放一些常用的内置指令和内置管道等。
  • @angular/forms:存放表单相关的内置组件及内置指令等。
  • @angular/http:存放网络请求相关的服务等。
  • @angular/router:存放路由相关的组件和指令等。
  • @angular/platform-<x>:存放的是引导启动相关的工具。angular支持在多个平台下运行,不同的平台都有对应的启动工具,这些启动工具会被封装到不同的模块里,如浏览器的启动工具存放在@angular/platform-browser下,服务端渲染的启动工具存放在@angular/platform-server下。

Angular 模块是一个带有 @NgModule 装饰器的类,它接收一个用来描述模块属性的元数据对象

@NgModule的元数据属性:

  • declarations:模块内部Components/Directives/Pipes的列表,声明一下这个模块内部成员
  • providers:指定应用程序的根级别需要使用的service。(Angular2中没有模块级别的service,所有在NgModule中声明的Provider都是注册在根级别的Dependency Injector中)
  • imports导入其他module,其它module暴露的出的Components、Directives、Pipes等可以在本module的组件中被使用。比如导入CommonModule后就可以使用NgIf、NgFor等指令。
  • exports:用来控制将哪些内部成员暴露给外部使用。导入一个module并不意味着会自动导入这个module内部导入的module所暴露出的公共成员。除非导入的这个module把它内部导入的module写到exports中。
  • bootstrap:通常是app启动的根组件一般只有一个component。bootstrap中的组件会自动被放入到entryComponents中。
  • entryCompoenents: 不会在模板中被引用到的组件。这个属性一般情况下只有ng自己使用,一般是bootstrap组件或者路由组件,ng会自动把bootstrap、路由组件放入其中。 除非不通过路由动态将component加入到dom中,否则不会用到这个属性。

一个最简单的根模块:

//app/app.module.ts 文件:import { NgModule } from '@angular/core'; //从 @angular/core 中引入 NgModule 修饰器
import { BrowserModule } from '@angular/platform-browser';@NgModule({imports:      [ BrowserModule ],providers:    [ Logger ],declarations: [ AppComponent ],exports:      [ AppComponent ],bootstrap:    [ AppComponent ]
})export class AppModule { }//定义根模块

三、组件 (Components)

组件是构成Angular2应用的砖块。

包括三个部分:带有 @Component() 装饰器的 TypeScript 类、HTML 模板和样式文件。

@Component的元数据属性:

  • selector :css选择器,把该组件实例化在 HTML 中对应的选择器上。
  • styleUrls :在单独文件中声明组件的样式。
  • styles : 在组件内部声明样式。styles: ['h1 { font-weight: normal; }']
  • standalone:描述组件是否需要 .NgModule
  • template :一段 HTML,告诉应用如何渲染组件。
  • templateUrl : HTML文件相对路径或绝对 URL。 (不能与template 同时使用)

一个简单的组件:

import { Component } from '@angular/core';//从 @angular/core 中引入 NgModule 修饰器@Component({selector: 'hello-world',template: `<h2>Hello World</h2><p>This is my first component!</p>`
})
export class HelloWorldComponent {//在此类中的代码驱动组件的行为。
}

在html中使用此组件:

<hello-world></hello-world>

在一个Angular2的应用中,组件是一个属性结构,就好像html的DOM树一样,每个Angular2应用都有一个根组件,然后它会有一个个的子组件。得到的是一个组件树。每个组件(除了根组件)都有一个父组件,每个组件定义中“selector”的值,对应父组件中的一个html标签。

组件通信

在Angular中,有多种方法可以实现父子组件通信。

以下是几种常用的方法:

  •  输入属性(Input Properties)
  •  输出属性(Output Properties)
  •  服务(Services)
  •  ViewChild与ContentChild

1. 输入属性(Input Properties)

输入属性是一种用于从父组件向子组件传递数据的方法。通过使用@Input()装饰器,我们可以在子组件中定义一个公共属性来接收来自父组件的数据。

import { Component, Input } from '@angular/core';@Component({selector: 'app-child',template: '<p>{{ message }}</p>'
})
export class ChildComponent {@Input() message: string;
}

在上述代码中,我们使用@Input()装饰器来定义了一个名为message的输入属性。在子组件的模板中,我们使用插值表达式{{ message }}来展示接收到的消息。

2. 输出属性(Output Properties)

输出属性允许子组件向父组件传递信息。通过使用事件触发器和@Output()装饰器,我们可以在子组件中定义一个事件,并在适当的时候将数据作为事件参数发送给父组件。

import { Component, Output, EventEmitter } from '@angular/core';@Component({selector: 'app-child',template: '<button (click)="sendMessage()">Send Message</button>'
})
export class ChildComponent {@Output() messageEvent = new EventEmitter<string>();sendMessage() {this.messageEvent.emit('Hello from child component');}
}

在上述代码中,我们定义了一个名为messageEvent的输出属性,并使用EventEmitter来创建一个新的事件。在子组件中,当用户点击按钮时,我们通过调用sendMessage()方法并使用emit()方法来触发messageEvent事件,并将一个字符串作为参数传递给父组件。

3. 服务(Services)

服务是一种共享数据和状态的有效方式。通过创建一个共享的服务,我们可以在任何组件之间传递数据和共享状态。组件可以通过依赖注入服务,并使用服务提供的方法和属性进行通信。

import { Injectable } from '@angular/core';@Injectable()
export class DataService {private message: string;setMessage(message: string) {this.message = message;}getMessage() {return this.message;}
}

在上述代码中,我们创建了一个名为DataService的服务,并在其中定义了一个私有的message属性和相应的设置和获取方法。通过在需要访问该数据的组件中注入DataService,我们可以在组件之间共享数据。

4. ViewChild与ContentChild

通过使用ViewChild和ContentChild装饰器,我们可以在父组件中获取对子组件的引用,并直接调用子组件的方法或访问其属性。这种方法适用于需要直接与子组件进行交互的情况。

import { Component, ViewChild } from '@angular/core';
import { ChildComponent } from './child.component';@Component({selector: 'app-parent',template: `<app-child></app-child><button (click)="callChildMethod()">Call Child Method</button>`
})
export class ParentComponent {@ViewChild(ChildComponent) childComponent: ChildComponent;callChildMethod() {this.childComponent.childMethod();}
}

在上述代码中,我们使用@ViewChild()装饰器来获取对ChildComponent的引用,并将其赋值给childComponent属性。然后,在父组件的模板中,我们使用一个按钮来触发callChildMethod()方法,该方法会调用子组件中的childMethod()方法。

四、数据绑定(Data binding)

Angular2的数据更新检测是在每个组件上有一个检测器。这样,就算应用中有再多绑定的变量,当有一个数据修改后,也只是对应的那个组件的检测器被触发,来检查它以及它所有的子组件的数据修改。

Angular 添加了一些语法元素以扩展 HTML,让你可以从组件中插入动态值。当组件的状态更改时,Angular 会自动更新已渲染的 DOM。

数据绑定的语法有四种形式:

1、插值 {{}} : 在 HTML 标签中显示组件值。(单向)

<h3>
{{title}}
<img src="{{ImageUrl}}">
</h3>

2、属性绑定 []: 把元素的属性设置为组件中属性的值。(单向)

<img [src]="userImageUrl">

3、事件绑定 (): 通过在圆括号中指定事件名称来声明一个事件监听器(单向)

//在组件方法名被点击时触发
<button (click)="sayMessage()">保存</button>//组件类中定义的方法:
sayMessage() {alert(this.message);
}

4、双向绑定 []  (): 使用Angular里的NgModel指令可以更便捷的进行双向绑定。

<input [value]="currentUser.firstName"(input)="currentUser.firstName=$event.target.value" >

双向绑定就是用户在页面上修改这个值时,这个值就会直接反馈到组件中。同样,如果在组件中通过某种方式修改了这个值,页面上,也会显示最新的值。

对于上面的 ​[]​ ​()​​​  两种类型的绑定,可以理解成’输入’和’输出’。 ​​

五、服务(Services)

Angular2并没有对服务的定义做任何的规则限制,任何的类都可以被定义成服务,这个类中可以包含业务方法,也可以包含环境配置变量。

一个简单的服务:

export class loggerServices {log(msg: any)   { console.log(msg); }error(msg: any) { console.error(msg); }warn(msg: any)  { console.warn(msg); }
}

我们只需要定义一个class,并把它export就可以了。

六、依赖注入 (Dependency Injection)

Angular借用了java等语言中某些容器库的概念,它将所有service实例的创建都由容器来完成。当一个service需要引用另一个service的时候,不需要先创建service实例,然后通过实例调用它的方法或属性,而是直接从容器中获取相应service的实例,无需我们操心如何实例化它们。

在Angular2中,依赖注入 (Dependency Injection) 主要是用于管理service实例的注入

使用 @Injectable 装饰器以声明此类可以被注入。

@Injectable​​ 
export class HeroService {
...
}

然后就可以在其它地方注入并使用它。

1:提供依赖项

  • 组件级别,使用 @Component 装饰器的 providers字段。在这种情况下,HeroService将可用于此组件的所有实例,以及它的模板中使用的其他组件和指令。也就是说,在当前节点,以及它所有的子节点的组件上,HeroService类的实例是共用的,它们都共享一个服务实例。例如:

@Component({selector: '...',template: '...',providers: [HeroService]
})
class HeroListComponent {}
  • NgModule 级别,要使用 @NgModule 装饰器的 providers字段。在这种情况下,HeroService可用于此 NgModule ,或与本模块位于同一个 ModuleInjector 的其它模块中声明的所有组件、指令和管道。当你向特定的 NgModule 注册提供者时,同一个服务实例可用于该 NgModule 中的所有组件、指令和管道。要理解所有边缘情况,参见多级注入器。例如:

@NgModule({declarations: [...]providers: [HeroService]
})
class HeroListModule {}
  • 在应用根级别,允许将其注入应用的其他类中。这可以通过将 providedIn: 'root'字段添加到 @Injectable 装饰器来实现:

@Injectable({providedIn: 'root'
})
class HeroService {}

当你在根级别提供服务时,Angular 会创建一个 HeroService 的共享实例,并将其注入到任何需要它的类中。在 @Injectable 元数据中注册提供者还允许 Angular 通过从已编译的应用程序中删除没用到的服务来优化应用程序,这个过程称为摇树优化(tree-shaking)。

2:注入依赖项

最常见方法是在类的构造函数中声明它。当 Angular 创建组件、指令或管道类的新实例时,它会通过查看构造函数的参数类型来确定该类需要哪些服务或其他依赖项。例如,如果 HeroListComponent 要用 HeroService,则构造函数可以如下所示:

@Component({ … })
class HeroListComponent {constructor(private service: HeroService) {}
}

相关文章:

Angular 2 学习笔记

Angular 2 应用主要由以下 几个部分组成&#xff1a; 1、模块 (Modules)&#xff1a; 2、组件 (Components)&#xff1a; 3、模板 (Templates)​​​​​​​&#xff1a; 4、元数据 (Metadata)&#xff1a; 5、数据绑定 (Data Binding) 6、指令 (Directives) 7、服务 (Servic…...

xcode 修改 target 中设备朝向崩溃

修改xcode的target中的设备朝向导致崩溃。 从日志上看好像没有什么特别的信息。 之后想了想&#xff0c;感觉这个应该还是跟xcode的配置有关系&#xff0c;不过改动的地方好像也只有plist。 就又翻腾了半天plist中的各种配置项&#xff0c;再把所有的用户权限提示相关的东西之…...

ZLMediaKit 编译以及测试(Centos 7.9 环境)

文章目录 一、前言二、编译器1、获取代码2、编译器2.1 编译器版本要求2.2 安装编译器 3、安装cmake4、依赖库4.1 依赖库列表4.2 安装依赖库4.2.1 安装libssl-dev和libsdl-dev4.2.2 安装 ffmpeg-devel依赖和ffmpeg依赖 三、构建和编译项目&#xff08;启用WebRTC功能&#xff09…...

汽车清除积碳和清洗节气门

汽车清除积碳和清洗节气门 汽车需要清除积碳的部位检查积碳方法&#xff1a; 清除积碳和清洗节气门风险&#xff1a;燃油宝 第一次清除积碳1万公里2万公里3万公里--5万公里6万公里以上 汽车需要清除积碳的部位 节气门喷油嘴进气道燃烧室 检查积碳方法&#xff1a; 建议每3到5…...

RocketMQ 总体概括

目录 概述RocketMQ 领域模型MQ 解决的问题电商平台案例初步设计引入中间件设计 MQ 选型结束 概述 官网地址 RocketMQ 领域模型 官方领域模型概述 下面图&#xff0c;是在自己理解的基础上&#xff0c;对官方的模型图添加了一些。 Topic&#xff1a;主题&#xff0c;可以理解…...

使用qemu在arm上模拟x86并运行docker

背景 有一个x86的docker镜像&#xff0c;但是需要运行在aarch64(arm64)上&#xff0c;无奈只能用qemu模拟x86的架构&#xff0c;但是最终没有实现。 原因分析&#xff1a;可能是使用的server版本的ubuntu镜像&#xff0c;建议之后换用desktop版本的ubuntu18镜像&#xff08;猜…...

IIS配置多域名跨域

搜索了一轮&#xff0c;自己实践发现iis中填多条Access-Control-Allow-Origin记录、逗号分隔、正则表达式这些是不行的。另外好像无论Ngxin还是Tomcat等都要rewrite之类的方法。由于仅仅是测试&#xff0c;所以暂时用*通配符算了。记录一下参考&#xff0c;要的时候再研究 CORS…...

el-form表单校验输入框值为0时 提示校验不通过

el-form表单校验输入框值为0时提示校验不通过 配置validator自定义校验方法 这里举例在结构代码里加入校验规则 <el-form-item:prop"num":rules"[{required: true,message: 请输入数量,trigger: change,},{validator,trigger: blur}]" ><el-inpu…...

Vue3后台管理-项目总结

后台管理 1. 动态路由2. 动态侧边栏菜单 持续更新中。。。 1. 动态路由 后台路由模型数据 &#xff08;如果后端不知道怎么转为 这种树结构的路由&#xff0c;可以参考 普通数组转树结构的数组&#xff09; const dynamicRoutes [{path: /,name: Layout,redirect: /home,comp…...

利用Pytorch预训练模型进行图像分类

Use Pre-trained models for Image Classification. # This post is rectified on the base of https://learnopencv.com/pytorch-for-beginners-image-classification-using-pre-trained-models/# And we have re-orginaized the code script.预训练模型(Pre-trained models)…...

MSF学习

之前的渗透测试中 其实很少用到 cs msf 但是在实际内网的时候 可以发现 msf cs 都是很好用的 所以现在我来学习一下 msf的使用方法 kali自带msf https://www.cnblogs.com/bmjoker/p/10051014.html 使用 msfconsole 启动即可 首先就是最正常的木马生成 所以这里其实只需…...

Mybatis与Spring结合深探——MapperFactoryBean的奥秘

文章目录 前言MapperFactoryBean的工作原理底层实现剖析MapperFactoryBean的checkDaoConfig()方法总结 MapperFactoryBean的getObject()方法 思考联想后续 系列相关相关文章究竟FactoryBean是什么&#xff1f;深入理解Spring的工厂神器超硬核解析Mybatis动态代理原理&#xff0…...

processon使用及流程图和泳道图的绘画(登录界面流程图,门诊流程图绘制门诊泳道图,住院泳道图,OA会议泳道图),Axure自定义元件

目录 一.processon图形的使用场景介绍 二.流程图绘画 三.泳道图的绘画 1.绘制门诊流程图绘制门诊泳道图 2. 绘制住院泳道图​编辑 3.绘制药库采购入库流程图 4.绘制OA会议泳道图 四.Axure自定义元件 1.Axure载入元件库 一.processon图形的使用场景介绍 二.流程图绘画 示例&…...

【虹科干货】关于JSON数据库

文章速览&#xff1a; 什么是JSON什么是JSON数据库JSON数据库的显著优势关于JSON数据库的Q&A 如何理解JSON数据库&#xff1f;作为NoSQL数据库的一种类型&#xff0c;JSON数据库有哪些优势呢&#xff1f;JSON数据库如何运作&#xff0c;它为应用程序开发者带来了哪些价值呢…...

区块链的可拓展性研究【03】扩容整理

为什么扩容&#xff1a;在layer1上&#xff0c;交易速度慢&#xff0c;燃料价格高 扩容的目的&#xff1a;在保证去中心化和安全性的前提下&#xff0c;提升交易速度&#xff0c;更快确定交易&#xff0c;提升交易吞吐量&#xff08;提升每秒交易量&#xff09; 目前方案有&…...

golang学习笔记——互斥锁sync.Mutex、计数器sync.WaitGroup、读写锁sync.RWMutex

文章目录 互斥锁&#xff1a; sync.Mutexsync.WaitGroup 计数器例子func (*WaitGroup) Addfunc (*WaitGroup) Donefunc (*WaitGroup) Wait 读写互斥锁参考资料 临界区总是需要通过同步机制进行保护的&#xff0c;否则就会产生竞态条件&#xff0c;导致数据不一致。 互斥锁&…...

MFC 加载本地文件设置图标

基于单文件/多文件版 1、在CMainFrame中设置 int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct) {//...........// 从本地文件加载图标HICON hIcon (HICON)::LoadImage(NULL, L"./vip.ico", IMAGE_ICON, 0, 0, LR_LOADFROMFILE);if (hIcon){ // 设置窗口图…...

飞天使-linux操作的一些技巧与知识点6-ansible结合jinja2使用,可规范化进行自动化管控

文章目录 在议playbook虚拟环境中安装ansibleplaybook 结合变量的一些演示普通的vars_files 变量&#xff0c;在同级目录创建目录使用host_vars 定义变量group_vars定义变量根据不同系统操作不同版本传递多个外置变量举例几个不同的示例factswhenloophandlers 与 notifytags 任…...

ROS2 Control分析讲解

ROS2 Control 文章目录 前言简述组成安装 框架Controller ManagerResource ManagerControllersUser Interfaces Hardware ComponentsURDF中的硬件描述机器人运行框架 总结 前言 ros2_control是一个使用&#xff08;ROS 2&#xff09;进行机器人&#xff08;实时&#xff09;控…...

Java TCP(一对一)聊天简易版

客户端 import java.io.*; import java.net.Socket; import java.util.Date; import javax.swing.*;public class MyClient {private JFrame jf;private JButton jBsend;private JTextArea jTAcontent;private JTextField jText;private JLabel JLcontent;private Date data;p…...

uniapp 对接腾讯云IM群组成员管理(增删改查)

UniApp 实战&#xff1a;腾讯云IM群组成员管理&#xff08;增删改查&#xff09; 一、前言 在社交类App开发中&#xff0c;群组成员管理是核心功能之一。本文将基于UniApp框架&#xff0c;结合腾讯云IM SDK&#xff0c;详细讲解如何实现群组成员的增删改查全流程。 权限校验…...

使用VSCode开发Django指南

使用VSCode开发Django指南 一、概述 Django 是一个高级 Python 框架&#xff0c;专为快速、安全和可扩展的 Web 开发而设计。Django 包含对 URL 路由、页面模板和数据处理的丰富支持。 本文将创建一个简单的 Django 应用&#xff0c;其中包含三个使用通用基本模板的页面。在此…...

Lombok 的 @Data 注解失效,未生成 getter/setter 方法引发的HTTP 406 错误

HTTP 状态码 406 (Not Acceptable) 和 500 (Internal Server Error) 是两类完全不同的错误&#xff0c;它们的含义、原因和解决方法都有显著区别。以下是详细对比&#xff1a; 1. HTTP 406 (Not Acceptable) 含义&#xff1a; 客户端请求的内容类型与服务器支持的内容类型不匹…...

mongodb源码分析session执行handleRequest命令find过程

mongo/transport/service_state_machine.cpp已经分析startSession创建ASIOSession过程&#xff0c;并且验证connection是否超过限制ASIOSession和connection是循环接受客户端命令&#xff0c;把数据流转换成Message&#xff0c;状态转变流程是&#xff1a;State::Created 》 St…...

基于Flask实现的医疗保险欺诈识别监测模型

基于Flask实现的医疗保险欺诈识别监测模型 项目截图 项目简介 社会医疗保险是国家通过立法形式强制实施&#xff0c;由雇主和个人按一定比例缴纳保险费&#xff0c;建立社会医疗保险基金&#xff0c;支付雇员医疗费用的一种医疗保险制度&#xff0c; 它是促进社会文明和进步的…...

Python爬虫实战:研究feedparser库相关技术

1. 引言 1.1 研究背景与意义 在当今信息爆炸的时代,互联网上存在着海量的信息资源。RSS(Really Simple Syndication)作为一种标准化的信息聚合技术,被广泛用于网站内容的发布和订阅。通过 RSS,用户可以方便地获取网站更新的内容,而无需频繁访问各个网站。 然而,互联网…...

Leetcode 3577. Count the Number of Computer Unlocking Permutations

Leetcode 3577. Count the Number of Computer Unlocking Permutations 1. 解题思路2. 代码实现 题目链接&#xff1a;3577. Count the Number of Computer Unlocking Permutations 1. 解题思路 这一题其实就是一个脑筋急转弯&#xff0c;要想要能够将所有的电脑解锁&#x…...

OkHttp 中实现断点续传 demo

在 OkHttp 中实现断点续传主要通过以下步骤完成&#xff0c;核心是利用 HTTP 协议的 Range 请求头指定下载范围&#xff1a; 实现原理 Range 请求头&#xff1a;向服务器请求文件的特定字节范围&#xff08;如 Range: bytes1024-&#xff09; 本地文件记录&#xff1a;保存已…...

BCS 2025|百度副总裁陈洋:智能体在安全领域的应用实践

6月5日&#xff0c;2025全球数字经济大会数字安全主论坛暨北京网络安全大会在国家会议中心隆重开幕。百度副总裁陈洋受邀出席&#xff0c;并作《智能体在安全领域的应用实践》主题演讲&#xff0c;分享了在智能体在安全领域的突破性实践。他指出&#xff0c;百度通过将安全能力…...

Java求职者面试指南:Spring、Spring Boot、MyBatis框架与计算机基础问题解析

Java求职者面试指南&#xff1a;Spring、Spring Boot、MyBatis框架与计算机基础问题解析 一、第一轮提问&#xff08;基础概念问题&#xff09; 1. 请解释Spring框架的核心容器是什么&#xff1f;它在Spring中起到什么作用&#xff1f; Spring框架的核心容器是IoC容器&#…...