Skip to content

Dependency Injection and Wiring

**Referenced Files in This Document** - [[wire.go]](file/bi-analysis/cmd/bi-analysis/wire.go) - [[wire_gen.go]](file/bi-analysis/cmd/bi-analysis/wire-gen.go) - [[main.go]](file/bi-analysis/cmd/bi-analysis/main.go) - [[biz.go]](file/bi-analysis/internal/biz/biz.go) - [[data.go]](file/bi-analysis/internal/data/data.go) - [[server.go]](file/bi-analysis/internal/server/server.go) - [[service.go]](file/bi-analysis/internal/service/service.go) - [[dict.go]](file/bi-analysis/internal/service/dict.go) - [[conf.proto]](file/bi-analysis/internal/conf/conf.proto) - [[common.proto]](file/bi-common/conf/common.proto)

Table of Contents

  1. Introduction
  2. Project Structure
  3. Core Components
  4. Architecture Overview
  5. Detailed Component Analysis
  6. Dependency Analysis
  7. Performance Considerations
  8. Troubleshooting Guide
  9. Conclusion

Introduction

This document explains the dependency injection and service wiring mechanism used in bi-server’s microservices, focusing on the Wire framework integration. It covers how services are registered via ProviderSet, how automatic dependency resolution constructs the application graph, and how the generated wiring code instantiates and composes services. It also documents configuration binding, service dependencies, interface implementations, and testing strategies with isolated mocks.

Project Structure

The bi-analysis service demonstrates the wiring pattern:

  • Entry point initializes configuration, logging, registry, and invokes the Wire injector to produce a Kratos application.
  • Wire injects services from internal layers: data, biz, server, and service, then wires them into HTTP and gRPC servers.
  • Configuration is defined in protobuf and loaded from Nacos, then scanned into a bootstrap structure.

Diagram sources

Section sources

Core Components

  • Wire injector stub and generated injector:
    • The injector stub defines a function that Wire will resolve and replace with generated code.
    • The generated injector wires together data repositories, business use cases, and service implementations, then creates HTTP and gRPC servers and a Kratos application.
  • ProviderSet registrations:
    • Data layer registers constructors for repositories, clients, transactions, and the core Data wrapper.
    • Biz layer registers use cases for domain logic.
    • Server layer registers HTTP and gRPC server constructors.
    • Service layer registers gRPC/HTTP service implementations.
  • Configuration binding:
    • Bootstrap configuration includes service name/version, server, data, log, snowflake, and auth settings.
    • Common configuration messages define server transport, data sources, Redis, Kafka, logging, and JWT auth.

Section sources

Architecture Overview

The runtime wiring flow:

  • main loads configuration from Nacos, sets up logging and registry, then calls the Wire injector.
  • The injector resolves constructor dependencies across data, biz, server, and service layers.
  • The injector returns a Kratos application composed of HTTP and gRPC servers and a cleanup function.

Diagram sources

Detailed Component Analysis

Wire Injector and Generated Graph

  • Injector stub:
    • Declares a function returning a Kratos app and a cleanup function, depending on configuration and external clients.
    • Uses Wire’s panic-based build trigger to generate the injector.
  • Generated injector:
    • Creates the Data layer, then repositories and use cases.
    • Instantiates services that depend on use cases and external clients.
    • Builds HTTP and gRPC servers with the services and starts the Kratos app.
    • Returns a cleanup function that tears down resources in reverse order.

Diagram sources

Section sources

Data Layer Wiring

  • ProviderSet registers constructors for repositories, clients, transactions, and the Data wrapper.
  • Data wrapper exposes database and Redis clients and provides transaction helpers.
  • Transactions support both direct transaction execution and context-aware transaction propagation.

Diagram sources

Section sources

Business Layer Wiring

  • ProviderSet registers use cases for domain logic (dimension, table, field, field group, query, template, field meta, home, field visible config).
  • Use cases depend on repositories and the Data layer’s transaction support.

Diagram sources

Section sources

Service Layer Wiring

  • ProviderSet registers service implementations for gRPC/HTTP endpoints.
  • Example: DictService depends on multiple use cases and external clients.

Diagram sources

Section sources

Server Layer Wiring

  • ProviderSet registers HTTP and gRPC server constructors.
  • HTTP server receives service instances and auth configuration.
  • Remote authentication middleware integrates with a tenant service client.

Diagram sources

Section sources

Configuration Binding

  • Bootstrap configuration binds service identity, server transport, data sources, logging, snowflake, and auth.
  • Common configuration messages define server, data, Redis, Kafka, logging, and JWT settings.

Diagram sources

Section sources

Dependency Analysis

  • Coupling and cohesion:
    • Each layer exports a ProviderSet of constructors, enabling loose coupling and high cohesion per layer.
    • Services depend on abstractions (use cases) rather than concrete repositories, improving testability.
  • External dependencies:
    • Kratos for transport and application lifecycle.
    • Nacos for configuration and service registration.
    • gRPC clients for cross-service communication.
  • Circular dependencies:
    • None observed in the analyzed files; wiring is acyclic and top-down.

Diagram sources

Section sources

Performance Considerations

  • Resource cleanup:
    • The generated injector returns a cleanup function that closes clients and connections in reverse order, preventing resource leaks.
  • Optional Redis:
    • Data initialization tolerates missing Redis configuration with a warning, avoiding hard failures in environments where Redis is optional.
  • Transaction propagation:
    • Context-aware transactions enable efficient reuse of DB handles across calls.

Section sources

Troubleshooting Guide

  • Wiring errors:
    • Verify that all constructor signatures match ProviderSet entries and that dependencies are resolvable.
    • Ensure the build tag for the injector stub is present so the stub is excluded from production builds.
  • Configuration loading:
    • Confirm Nacos configuration file path and keys align with the Bootstrap structure.
    • Validate that common configuration messages (server, data, auth) are correctly populated.
  • Service startup:
    • Check that the Kratos application includes both HTTP and gRPC servers and that the registrar is set when a registry client exists.

Section sources

Conclusion

The bi-server services adopt a clean, layered architecture with explicit dependency injection via Wire. ProviderSet registrations decouple construction from usage, while the generated injector ensures deterministic composition of repositories, use cases, services, and transport servers. Configuration binding through protobuf and Nacos enables environment-specific setups. This approach improves maintainability, testability, and operational reliability by isolating concerns, enforcing interface-based dependencies, and centralizing resource lifecycle management.