Pular para conteúdo

Aula 18 - Injeção de Dependências Avançada e Scopes 💉

Objetivo Pedagógico

Objetivo: Domínio do sistema de Injeção de Dependências (DI) hierárquica do Angular, provedores customizados, função inject() e resolução de scopes.


📑 1. Fundamentos Teóricos & Análise Técnica

O sistema de Injeção de Dependências (DI) do Angular é uma das mais avançadas implementações do princípio de Inversão de Controle (IoC) no desenvolvimento frontend. Diferente de frameworks que utilizam escopos globais simples, o Angular implementa um sistema de Injetores Hierárquicos, permitindo que dependências sejam isoladas por módulo, rota ou instância de componente.

A hierarquia de injetores é estruturada em duas árvores paralelas: 1. Árvore de Injetores de Ambiente (EnvironmentInjector): Provê serviços globais (providedIn: 'root') ou restritos a rotas específicas com providers: [...] no roteador. 2. Árvore de Injetores de Elementos (ElementInjector): Criada implicitamente para cada componente ou diretiva com a propriedade providers: [...] ou viewProviders: [...].

Com a introdução da função inject(), o Angular permite a injeção funcional em construtores, funções utilitárias ou inicializadores de propriedades, eliminando o acoplamento de parâmetros repetitivos no constructor de classes que herdam de classes base.

📐 Arquitetura Conceitual & Diagrama de Fluxo

graph TD
    Root["Root Injector (providedIn: 'root')<br>Singletons Globais (Auth, HTTP)"] --> Route["Route Injector (Rota /dashboard)<br>Instâncias Escopadas à Rota"]
    Route --> CompParent["Element Injector (DashboardComponent)<br>Serviço de Estado do Dashboard"]
    CompParent --> CompChild["Element Injector (WidgetComponent)<br>Configurações Locais do Widget"]
    style Root fill:#e3f2fd,stroke:#1565c0
    style Route fill:#fff3e0,stroke:#e65100
    style CompParent fill:#e8f5e9,stroke:#2e7d32
    style CompChild fill:#f3e5f5,stroke:#7b1fa2

🔍 Pilares e Diretrizes Técnicas

Nesta unidade, aprofundamos os seguintes conceitos fundamentais: - Função Funcional inject(): Substituição moderna da injeção via construtor, permitindo composição funcional de lógica. - Modificadores de Resolução: Controle fino da busca de instâncias via @Optional(), @Self(), @SkipSelf() e @Host(). - Tokens de Injeção (InjectionToken): Injeção tipada de valores primitivos, configurações e interfaces abstratas. - Tree-shakable Providers: Serviços declarados com providedIn: 'root' são removidos do bundle final se não forem referenciados.


🛠️ 2. Implementação Prática em Angular Dependency Injection

Abaixo está a implementação técnica de referência, estruturada com padrões de engenharia de software e foco em robustez:

// auth.service.ts (DI Funcional e InjectionToken)
import { Injectable, InjectionToken, inject } from '@angular/core';
import { HttpClient } from '@angular/common/http';

export interface AppApiConfig {
  baseUrl: string;
  timeoutMs: number;
}

export const API_CONFIG = new InjectionToken<AppApiConfig>('API_CONFIG', {
  providedIn: 'root',
  factory: () => ({ baseUrl: 'https://api.empresa.com/v1', timeoutMs: 5000 })
});

@Injectable({ providedIn: 'root' })
export class AuthService {
  // Injeção funcional com a função inject()
  private readonly http = inject(HttpClient);
  private readonly config = inject(API_CONFIG);

  getProfile() {
    return this.http.get(`${this.config.baseUrl}/auth/me`);
  }
}

💡 Análise Passo a Passo do Código

  1. Criação do Token: new InjectionToken<AppApiConfig> cria uma chave tipada e segura para injetar objetos literais.
  2. Uso da Função inject(): inject(HttpClient) obtém a dependência sem necessidade de declarar parâmetros verbosos no construtor.
  3. Escopo Root Garantido: providedIn: 'root' assegura uma única instância singleton compartilhada por toda a aplicação.

🎯 3. Próximos Passos & Sequência Didática