VOOZH about

URL: https://deepwiki.com/hypervel/event/6.1-factory-system-and-dependency-injection

⇱ Factory System and Dependency Injection | hypervel/event | DeepWiki


Loading...
Menu

Factory System and Dependency Injection

This page explains how the event system is assembled and wired together through factories and dependency injection. It covers the ConfigProvider, EventDispatcherFactory, and ListenerProviderFactory classes, which handle the complex initialization of the event system components and their dependencies. This includes how listeners are discovered from multiple sources (configuration files and annotations), how optional dependencies are lazily resolved, and how the system integrates with PSR-11 containers.

For information about the runtime behavior of the assembled components, see Core Event System. For details about the interfaces that define component contracts, see Contracts and Interfaces.


Overview

The factory system serves as the initialization layer that transforms configuration and annotations into a fully functional event system. Rather than requiring manual construction of complex object graphs, the factories encapsulate the assembly logic and enable container-based dependency resolution.

The system consists of three primary components:

ComponentPurposeLocation
ConfigProviderRegisters factory bindings with the DI containersrc/ConfigProvider.php1-22
EventDispatcherFactoryCreates and configures EventDispatcher instancessrc/EventDispatcherFactory.php1-25
ListenerProviderFactoryCreates ListenerProvider and populates it with listenerssrc/ListenerProviderFactory.php1-63

Sources: src/ConfigProvider.php1-22 src/EventDispatcherFactory.php1-25 src/ListenerProviderFactory.php1-63


Dependency Injection Configuration

ConfigProvider

The ConfigProvider class defines the dependency injection bindings that wire PSR-14 interfaces to their concrete implementations through factory classes.


Dependency Injection Bindings

The configuration maps PSR-14 standard interfaces to factory classes src/ConfigProvider.php15-18:

InterfaceFactoryPurpose
Psr\EventDispatcher\EventDispatcherInterfaceEventDispatcherFactoryPrimary event dispatcher
Psr\EventDispatcher\ListenerProviderInterfaceListenerProviderFactoryListener storage and retrieval

When application code requests EventDispatcherInterface from the container, the container invokes EventDispatcherFactory to create an instance. This indirection enables complex initialization logic without polluting the application layer.

Sources: src/ConfigProvider.php1-22


EventDispatcherFactory

The EventDispatcherFactory assembles the EventDispatcher with all its required dependencies and configures optional integrations through lazy resolvers.

Factory Construction Flow


Factory Initialization Steps

The factory performs the following operations src/EventDispatcherFactory.php14-23:

  1. Resolve ListenerProvider - Retrieves the ListenerProviderInterface from the container src/EventDispatcherFactory.php16 This ensures the dispatcher has access to registered listeners.

  2. Resolve Logger - Retrieves StdoutLoggerInterface for logging event dispatch activities src/EventDispatcherFactory.php17

  3. Construct Dispatcher - Creates EventDispatcher with the listener provider, logger, and container reference src/EventDispatcherFactory.php18

  4. Configure Queue Resolver - Sets a lazy resolver for the queue factory src/EventDispatcherFactory.php20 This closure-based approach delays queue system initialization until actually needed.

Lazy Dependency Resolution

The queue resolver pattern src/EventDispatcherFactory.php20 demonstrates lazy dependency resolution:


This closure is only invoked when the dispatcher needs to queue a listener. If the application never uses queued listeners, the QueueFactoryContract is never resolved, and the queue system doesn't need to be available. This enables graceful degradation when optional dependencies are absent.

Dependencies:

DependencyTypePurpose
ListenerProviderInterfaceRequiredProvides event-to-listener mappings
StdoutLoggerInterfaceRequiredLogs event dispatch activity
ContainerInterfaceRequiredResolves listener classes and dependencies
QueueFactoryContractOptional (lazy)Enables asynchronous event processing

Sources: src/EventDispatcherFactory.php1-25


ListenerProviderFactory

The ListenerProviderFactory is responsible for discovering listeners from multiple sources and registering them with the ListenerProvider. This factory implements a two-phase registration process: configuration-based registration and annotation-based registration.

Listener Discovery Architecture


Factory Invocation

The factory's __invoke method src/ListenerProviderFactory.php16-27 orchestrates the registration process:

  1. Creates a new ListenerProvider instance src/ListenerProviderFactory.php18
  2. Registers listeners from configuration src/ListenerProviderFactory.php21
  3. Registers listeners from annotations src/ListenerProviderFactory.php24
  4. Returns the populated provider src/ListenerProviderFactory.php26

Configuration-Based Registration

The registerConfig method src/ListenerProviderFactory.php29-41 reads the listeners configuration array and processes each entry:

Configuration Format:


The method handles two formats:

Annotation-Based Registration

The registerAnnotations method src/ListenerProviderFactory.php43-51 discovers listeners marked with the @Listener annotation:

  1. Iterates through all classes collected by AnnotationCollector src/ListenerProviderFactory.php45
  2. Checks for the Listener annotation on each class src/ListenerProviderFactory.php47
  3. Extracts priority from the annotation src/ListenerProviderFactory.php48
  4. Registers the listener with the extracted priority src/ListenerProviderFactory.php48

Listener Registration Process


The register method src/ListenerProviderFactory.php53-61 performs the actual registration:

  1. Resolve Listener - Retrieves the listener instance from the container src/ListenerProviderFactory.php55 This triggers any necessary dependency injection for the listener class.

  2. Verify Interface - Checks if the instance implements ListenerInterface src/ListenerProviderFactory.php56

  3. Extract Events - Calls the listen() method to get the array of event names the listener handles src/ListenerProviderFactory.php57

  4. Register Each Event - For each event, calls $provider->on() with the event name, the listener callable [$instance, 'process'], and priority src/ListenerProviderFactory.php58

Priority Handling:

The priority system allows control over listener execution order. The default priority is defined in ListenerData::DEFAULT_PRIORITY src/ListenerProviderFactory.php35 Higher priority values execute first.

Sources: src/ListenerProviderFactory.php1-63


Complete Initialization Sequence

The following diagram illustrates the full initialization flow from container bootstrapping through to a functional event system:


Initialization Phases:

  1. Configuration Phase - ConfigProvider returns dependency bindings to the container
  2. Listener Discovery Phase - ListenerProviderFactory discovers and registers all listeners
  3. Dispatcher Assembly Phase - EventDispatcherFactory creates the dispatcher with all dependencies
  4. Runtime Phase - Application uses the fully configured event system

Sources: src/ConfigProvider.php1-22 src/ListenerProviderFactory.php1-63 src/EventDispatcherFactory.php1-25


Dependency Graph

The complete dependency relationships between factory components and their products:


Dependency Types:

DependencyResolutionPurpose
ListenerProviderInterfaceEager (factory time)Must be available for dispatcher to function
StdoutLoggerInterfaceEager (factory time)Required for logging event activities
ConfigInterfaceEager (factory time)Needed for reading listener configuration
AnnotationCollectorEager (factory time)Static class for annotation discovery
QueueFactoryContractLazy (runtime)Only resolved when queuing listeners
TransactionManagerLazy (runtime)Only resolved when using after-commit events
BroadcastFactoryLazy (runtime)Only resolved when broadcasting events

The lazy resolution pattern for optional dependencies prevents initialization failures when those systems are unavailable, enabling the event system to function in reduced-capability mode.

Sources: src/EventDispatcherFactory.php1-25 src/ListenerProviderFactory.php1-63


Extension Points

The factory system provides several extension points for customization:

Custom Factory Implementation

To replace or extend factory behavior, override the factory binding in your application's ConfigProvider:


Programmatic Listener Registration

Beyond configuration and annotations, listeners can be registered programmatically after the ListenerProvider is constructed:


Additional Dependency Injection

Custom factories can inject additional dependencies by resolving them from the container:


Sources: src/EventDispatcherFactory.php1-25 src/ListenerProviderFactory.php1-63


Summary

The factory system provides a clean separation between:

  • Configuration - What components should exist and how they're wired (ConfigProvider)
  • Assembly - The logic for constructing components with dependencies (factory classes)
  • Runtime - The operational event system (dispatcher and provider)

This architecture enables:

  • Testability - Factories can be tested independently by providing mock containers
  • Flexibility - Custom factories can extend or replace default behavior
  • Lazy Loading - Optional dependencies are only resolved when needed
  • Multi-Source Registration - Listeners discovered from configuration files and annotations
  • Container Integration - Full PSR-11 compliance for framework interoperability

Sources: src/ConfigProvider.php1-22 src/EventDispatcherFactory.php1-25 src/ListenerProviderFactory.php1-63