Angular の依存関係注入システムの基本概念について話しましょう
この記事では、Angular について説明し、依存関係注入の基本的な概念を紹介します。
「大規模なフロントエンド プロジェクト向け」に設計されたフロントエンド フレームワークとして、Angular には実際に参考にして学ぶ価値のある設計が数多くあります。このシリーズは主に次の用途に使用されます。これらのデザインと機能を研究し、実現原理を研究します。この記事では、Angular の最大の機能である依存関係注入に焦点を当て、まず Angular の依存関係注入システムの基本的な概念をいくつか紹介します。
依存性注入
Angular フレームワークの依存性注入設計を紹介したいので、最初に依存性注入の基本概念を説明します。依存関係反転原則 (DIP)、制御反転 (IoC)、および依存関係注入 (DI) の概念はよく混同されるため、ここで簡単に説明します。 [関連チュートリアルの推奨事項: "angular チュートリアル"]
依存関係反転原理、制御反転、依存性注入
低結合、高凝集性です。これはおそらくあらゆるシステムの設計目標の 1 つであり、依存関係逆転原理や制御逆転の設計アイデアを含む、多くの設計パターンや概念がこの目的のために作成されてきました。
(1) 依存関係逆転原理 (DIP)。
依存関係逆転原則の元の定義は次のとおりです:
- 高レベルのモジュールは低レベルのモジュールに依存すべきではなく、両方ともその抽象化に依存する必要があります。
- 抽象化はすべきではない 詳細に依存する必要があり、詳細は抽象化に依存する必要があります。
簡単に言うと、モジュールは相互に直接依存するべきではなく、抽象ルール (インターフェイスまたは抽象クラス) に依存する必要があります。
(2) 制御の反転 (IoC)。
制御の反転の定義は、モジュール間の依存関係がプログラム内から外部にインスタンス化および管理されることです。つまり、オブジェクトが作成されると、そのオブジェクトはシステム内のすべてのオブジェクトを制御する外部エンティティによって制御され、そのオブジェクトが依存するオブジェクトの参照がそのオブジェクトに渡されます (注入されます)。
制御の反転を実装するには、主に 2 つの方法があります。
- 依存関係の挿入: 依存関係のオブジェクトを受動的に受け取る
- 依存関係のルックアップ: 依存関係のオブジェクトを積極的に要求する
##(3) 依存関係の注入。
依存性注入は、制御反転の最も一般的な手法です。 依存性反転と制御反転は相互に補完し合うため、多くの場合一緒に使用してモジュール間の結合を効果的に軽減できます。 Angular での依存関係の挿入Angular では、依存関係の挿入テクノロジも使用されます。クラスをインスタンス化するとき、DI フレームワークは、このクラスによって宣言された依存関係をクラスに提供します。(依存関係: を参照してください)クラスがその機能を実行するために必要なサービスまたはオブジェクト)。 Angular での依存関係の挿入は基本的にコンポーネントまたはモジュールを中心に展開し、主に新しく作成されたコンポーネントに依存関係を提供するために使用されます。 Angular の主な依存関係注入メカニズムは、インジェクター メカニズムです。:
- アプリケーションで必要な依存関係はすべて、アプリケーションのインジェクターを使用する必要があります。インジェクターは、このプロバイダーを使用して新しいインスタンスを作成できます。
- Angular は、完全なアプリケーション レベルのインジェクターと、起動時に必要なその他のインジェクターを作成します。
- #これには、主に 2 つの概念が含まれます。インジェクター injector
プロバイダ Provider を見てみましょう。 Injector インジェクター
Injector インジェクターは、依存関係を作成し、これらの依存関係を管理するコンテナーを維持し、それらを可能な限り再利用するために使用されます。インジェクターは依存関係のシングルトンを提供し、このシングルトン オブジェクトを複数のコンポーネントに注入します。
明らかに、依存関係の作成、管理、維持に使用されるコンテナーであるインジェクターの機能は非常に単純です。依存関係インスタンスの作成、依存関係インスタンスの取得、依存関係インスタンスの管理です。抽象クラスInjector
:export abstract class Injector { // 找不到依赖 static THROW_IF_NOT_FOUND = THROW_IF_NOT_FOUND; // NullInjector 是树的顶部 // 如果你在树中向上走了很远,以至于要在 NullInjector 中寻找服务,那么将收到错误消息,或者对于 @Optional(),返回 null static NULL: Injector = new NullInjector(); // 根据提供的 Token 从 Injector 检索实例 abstract get<T>( token: Type<T> | AbstractType<T> | InjectionToken<T>, notFoundValue?: T, flags?: InjectFlags ): T; // 创建一个新的 Injector 实例,该实例提供一个或多个依赖项 static create(options: { providers: StaticProvider[]; parent?: Injector; name?: string; }): Injector; // ɵɵdefineInjectable 用于构造一个 InjectableDef // 它定义 DI 系统将如何构造 Token,并且在哪些 Injector 中可用 static ɵprov = ɵɵdefineInjectable({ token: Injector, providedIn: "any" as any, // ɵɵinject 生成的指令:从当前活动的 Injector 注入 Token factory: () => ɵɵinject(INJECTOR), }); static __NG_ELEMENT_ID__ = InjectorMarkers.Injector; }
のソース コードからもそれを確認できます。つまり、共有する必要がある依存関係インスタンスをインジェクターに追加し、クエリと取得を行うことができます。トークン インジェクターを介してそれらを取得し、対応する依存関係インスタンスを取得します。
Angular のインジェクターは階層的であるため、依存関係を見つけるプロセスは、インジェクター ツリーを上にたどるプロセスでもあることに注意してください。 これは、Angular ではアプリケーションがモジュールに編成されているためです。詳細については、「5. モジュール編成
」を参照してください。一般にページの DOM はhtml をルートノードとするツリー構造になっており、これを基に Angular アプリケーション内のコンポーネントやモジュールもそれに付随するツリー構造になります。 インジェクターはコンポーネントとモジュールにサービスを提供し、モジュールと組織のツリー構造にもマウントされます。したがって、Injector はモジュール レベルとコンポーネント レベルにも分割されており、それぞれコンポーネントとモジュールの依存関係の特定のインスタンスを提供できます。インジェクターは継承可能です。つまり、指定されたインジェクターが依存関係を解決できない場合、親インジェクターに依存関係を解決するよう要求します。また、上記のコードから、インジェクターを作成することがわかります。<div class="code" style="position:relative; padding:0px; margin:0px;"><pre class='brush:php;toolbar:false;'>// 创建一个新的 Injector 实例,可传入 parent 父注入器
static create(options: {providers: StaticProvider[], parent?: Injector, name?: string}): Injector;</pre><div class="contentsignin">ログイン後にコピー</div></div><p>在某个注入器的范围内,服务是单例的。也就是说,在指定的注入器中最多只有某个服务的最多一个实例。如果不希望在所有地方都使用该服务的同一个实例,则可以通过注册多个注入器、并按照需要关联到组件和模块中的方式,来按需共享某个服务依赖的实例。</p><p>我们可以看到创建一个新的<code>Injector
实例时,传入的参数包括Provider
,这是因为Injector
不会直接创建依赖,而是通过Provider
来完成的。每个注入器会维护一个提供者的列表,并根据组件或其它服务的需要,用它们来提供服务的实例。
Provider 提供者
Provider 提供者用来告诉注入器应该如何获取或创建依赖,要想让注入器能够创建服务(或提供其它类型的依赖),必须使用某个提供者配置好注入器。
一个提供者对象定义了如何获取与 DI 令牌(token) 相关联的可注入依赖,而注入器会使用这个提供者来创建它所依赖的那些类的实例。
关于 DI 令牌:
- 当使用提供者配置注入器时,就会把提供者和一个 DI 令牌关联起来;
- 注入器维护一个内部令牌-提供者的映射表,当请求一个依赖项时就会引用它,令牌就是这个映射表的键。
提供者的类型很多,从官方文档中可以阅读它们的具体定义:
export type Provider = | TypeProvider | ValueProvider | ClassProvider | ConstructorProvider | ExistingProvider | FactoryProvider | any[];
提供者的解析过程如下:
function resolveReflectiveFactory( provider: NormalizedProvider ): ResolvedReflectiveFactory { let factoryFn: Function; let resolvedDeps: ReflectiveDependency[]; if (provider.useClass) { // 使用类来提供依赖 const useClass = resolveForwardRef(provider.useClass); factoryFn = reflector.factory(useClass); resolvedDeps = _dependenciesFor(useClass); } else if (provider.useExisting) { // 使用已有依赖 factoryFn = (aliasInstance: any) => aliasInstance; // 从根据 token 获取具体的依赖 resolvedDeps = [ ReflectiveDependency.fromKey(ReflectiveKey.get(provider.useExisting)), ]; } else if (provider.useFactory) { // 使用工厂方法提供依赖 factoryFn = provider.useFactory; resolvedDeps = constructDependencies(provider.useFactory, provider.deps); } else { // 使用提供者具体的值作为依赖 factoryFn = () => provider.useValue; resolvedDeps = _EMPTY_LIST; } // return new ResolvedReflectiveFactory(factoryFn, resolvedDeps); }
根据不同类型的提供者,通过解析之后,得到由注入器 Injector 使用的提供者的内部解析表示形式:
export interface ResolvedReflectiveProvider { // 键,包括系统范围内的唯一 id,以及一个 token key: ReflectiveKey; // 可以返回由键表示的对象的实例的工厂函数 resolvedFactories: ResolvedReflectiveFactory[]; // 指示提供者是多提供者,还是常规提供者 multiProvider: boolean; }
提供者可以是服务类ClassProvider
本身,如果把服务类指定为提供者令牌,那么注入器的默认行为是用new
来实例化那个类。
Angular 中的依赖注入服务
在 Angular 中,服务就是一个带有@Injectable
装饰器的类,它封装了可以在应用程序中复用的非 UI 逻辑和代码。Angular 把组件和服务分开,是为了增进模块化程度和可复用性。
用@Injectable
标记一个类,以确保编译器将在注入类时生成必要的元数据(元数据在 Angular 中也是很重要的一部分),以创建类的依赖项。
@Injectable
装饰器的类会在编译之后,得到 Angular 可注入对象:
// 根据其 Injectable 元数据,编译 Angular 可注入对象,并对结果进行修补 export function compileInjectable(type: Type<any>, srcMeta?: Injectable): void { // 该编译过程依赖 @angular/compiler // 可参考编译器中的 compileFactoryFunction compileInjectable 实现 }
Angular 中可注入对象(InjectableDef
)定义 DI 系统将如何构造 token 令牌,以及在哪些注入器(如果有)中可用:
export interface ɵɵInjectableDef<T> { // 指定给定类型属于特定注入器,包括 root/platform/any/null 以及特定的 NgModule providedIn: InjectorType<any> | "root" | "platform" | "any" | null; // 此定义所属的令牌 token: unknown; // 要执行以创建可注入实例的工厂方法 factory: (t?: Type<any>) => T; // 在没有显式注入器的情况下,存储可注入实例的位置 value: T | undefined; }
使用@Injectable()
的providedIn
时,优化工具可以进行 Tree-shaking 优化,从而删除应用程序中未使用的服务,以减小捆绑包尺寸。
总结
本文简单介绍了在 Angular 依赖注入体系中比较关键的几个概念,主要包括Injector
、Provider
和Injectable
。
对于注入器、提供者和可注入服务,我们可以简单地这样理解:
注入器用于创建依赖,会维护一个容器来管理这些依赖,并尽可能地复用它们。
一个注入器中的依赖服务,只有一个实例。
注入器需要使用提供者来管理依赖,并通过 token(DI 令牌)来进行关联。
提供者用于高速注入器应该如何获取或创建依赖。
可注入服务类会根据元数据编译后,得到可注入对象,该对象可用于创建实例。
更多编程相关知识,请访问:编程入门!!
以上がAngular の依存関係注入システムの基本概念について話しましょうの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

ホットAIツール

Undresser.AI Undress
リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover
写真から衣服を削除するオンライン AI ツール。

Undress AI Tool
脱衣画像を無料で

Clothoff.io
AI衣類リムーバー

Video Face Swap
完全無料の AI 顔交換ツールを使用して、あらゆるビデオの顔を簡単に交換できます。

人気の記事

ホットツール

メモ帳++7.3.1
使いやすく無料のコードエディター

SublimeText3 中国語版
中国語版、とても使いやすい

ゼンドスタジオ 13.0.1
強力な PHP 統合開発環境

ドリームウィーバー CS6
ビジュアル Web 開発ツール

SublimeText3 Mac版
神レベルのコード編集ソフト(SublimeText3)

ホットトピック











Angular.js は、動的アプリケーションを作成するための無料でアクセスできる JavaScript プラットフォームです。 HTML の構文をテンプレート言語として拡張することで、アプリケーションのさまざまな側面を迅速かつ明確に表現できます。 Angular.js は、コードの作成、更新、テストに役立つさまざまなツールを提供します。さらに、ルーティングやフォーム管理などの多くの機能も提供します。このガイドでは、Ubuntu24 に Angular をインストールする方法について説明します。まず、Node.js をインストールする必要があります。 Node.js は、ChromeV8 エンジンに基づく JavaScript 実行環境で、サーバー側で JavaScript コードを実行できます。ウブにいるために

インターネットの急速な発展に伴い、フロントエンド開発テクノロジーも常に改善され、反復されています。 PHP と Angular は、フロントエンド開発で広く使用されている 2 つのテクノロジーです。 PHP は、フォームの処理、動的ページの生成、アクセス許可の管理などのタスクを処理できるサーバー側スクリプト言語です。 Angular は、単一ページ アプリケーションの開発やコンポーネント化された Web アプリケーションの構築に使用できる JavaScript フレームワークです。この記事では、PHPとAngularをフロントエンド開発に使用する方法と、それらを組み合わせる方法を紹介します。

Angular Universal をご存知ですか?これは、Web サイトがより優れた SEO サポートを提供するのに役立ちます。

Angularでモナコエディタを使用するにはどうすればよいですか?以下の記事は、最近業務で使用したangularでのmonaco-editorの使い方を記録したものですので、皆様のお役に立てれば幸いです。

この記事では、Angular の独立コンポーネント、Angular で独立コンポーネントを作成する方法、および既存のモジュールを独立コンポーネントにインポートする方法について説明します。

Angular フレームワークのコンポーネントのデフォルトの表示動作は、ブロックレベルの要素ではありません。この設計の選択により、コンポーネント スタイルのカプセル化が促進され、開発者が各コンポーネントの表示方法を意識的に定義することが促進されます。 CSS プロパティの表示を明示的に設定することで、Angular コンポーネントの表示を完全に制御して、目的のレイアウトと応答性を実現できます。

Angular プロジェクトが大きすぎます。適切に分割するにはどうすればよいですか?次の記事では、Angular プロジェクトを合理的に分割する方法を紹介します。

認証は、Web アプリケーションの最も重要な部分の 1 つです。このチュートリアルでは、トークンベースの認証システムと、それが従来のログイン システムとどのように異なるかについて説明します。このチュートリアルを終えると、Angular と Node.js で書かれた完全に動作するデモが表示されます。従来の認証システム トークンベースの認証システムに進む前に、従来の認証システムを見てみましょう。ユーザーはログイン フォームにユーザー名とパスワードを入力し、[ログイン] をクリックします。リクエストを行った後、データベースにクエリを実行してバックエンドでユーザーを認証します。リクエストが有効な場合、データベースから取得したユーザー情報を使用してセッションが作成され、セッション情報が応答ヘッダーで返され、セッション ID がブラウザに保存されます。対象となるアプリケーションへのアクセスを提供します。
