Fact-checked by Grok 2 weeks ago

Service locator pattern

The service locator pattern is a that encapsulates the processes involved in obtaining and managing services through a central registry, known as the service locator, which decouples client code from the concrete implementations, locations, and complexities of those services. Introduced as part of the Core J2EE Patterns to address challenges in enterprise applications, the pattern abstracts interactions with components like Enterprise JavaBeans (EJBs) and by hiding Java Naming and Directory Interface (JNDI) lookups, initial creation, and vendor-specific dependencies. In this structure, clients request services explicitly from the locator (e.g., via a like getService()), which checks a cache for existing instances; if none is found, it uses an initializer to create and register the service, often supporting type-safe retrieval for better reliability. While the pattern promotes modularity by centralizing service access and enabling runtime configuration—such as switching implementations without altering client code—it is frequently critiqued as an in modern . Critics argue that it obscures dependencies, making difficult because services are resolved at runtime rather than declared explicitly, and it can lead to tight with the locator itself, contrasting with approaches that invert control and enhance testability. Despite these drawbacks, it remains useful in legacy systems, certain game development contexts for decoupling subsystems, and scenarios requiring dynamic .

Overview

Definition

The service locator pattern is a that provides a centralized registry, known as the service locator, which acts as a single point of access for client objects to retrieve required services or dependencies without directly or to their implementations. This approach enables clients to request services by name or key through the locator, which then resolves and returns the appropriate instance, thereby encapsulating the complexity of and . Key characteristics of the pattern include its role as a global access point that promotes between clients and service providers, allowing for easier substitution of implementations at runtime without modifying client code. By hiding the details of how services are located—such as through a or —the pattern decouples clients from specific service classes, facilitating and in applications. The pattern originated in the context of enterprise JavaBeans (EJB) development, where it was used to encapsulate lookups in the Java Naming and Directory Interface (JNDI) for accessing distributed components. It was formalized and popularized in Martin Fowler's 2002 book Patterns of Enterprise Application Architecture, which described it as a mechanism for in service-oriented architectures. In essence, the service locator functions like a phone directory for services, where clients dial a known number (service identifier) to connect rather than hardwiring direct contacts, contrasting with approaches like that pass dependencies explicitly to clients.

Motivation

The service locator pattern addresses key challenges in dependency management within software applications, particularly the tight coupling between client code and concrete service implementations. In traditional designs, clients directly instantiate or reference specific services, leading to compile-time dependencies that hinder and reusability. This coupling makes it difficult to alter service behaviors without modifying client code, complicating maintenance in evolving systems. By centralizing service access through a locator, the pattern decouples clients from implementation details, allowing them to request services by abstract interfaces rather than concrete classes. A primary motivation arises from the difficulty in testing due to hardcoded dependencies, where replacing real services with mocks or stubs requires invasive code changes. The pattern mitigates this by enabling registration of alternative implementations, such as test doubles, without altering client logic. Additionally, it supports configuration of services, which is essential for adapting to different environments like development, staging, or production without recompilation. In distributed systems, such as those using JNDI for lookups, repeated direct invocations create code duplication and performance overhead from resource-intensive operations like context creation and object retrieval. In large-scale applications, like web services or enterprise systems, multiple components often require access to shared resources, such as database connections or messaging queues, without knowledge of their underlying specifics. The service locator provides a unified for these lookups, reducing complexity and enabling efficient caching of results to avoid redundant operations. This is particularly relevant in environments with remote services, where direct client interactions with naming services like JNDI introduce vendor dependencies and failure-prone code. The pattern enhances modularity by facilitating the swapping of service implementations—for instance, using mock services during or alternative providers in production—while keeping client code unchanged. This promotes and easier evolution of systems. Emerging in the context of J2EE applications in the early 2000s, it builds on foundational ideas from (SOA), which emphasized decoupled, reusable services across distributed components.

Implementation

Components

The Service Locator pattern comprises a set of core architectural elements designed to centralize the management and retrieval of dependencies, promoting in software systems. The primary component is the Service Locator, a central registry class—often implemented as a —that acts as the unified entry point for accessing services across the application. This locator encapsulates the complexity of service discovery, such as hiding details like JNDI lookups in enterprise environments, and provides methods for service retrieval and management. Key responsibilities of the Service Locator include offering a lookup , typically named getService(String name), which returns an instance of the requested based on a , such as a string key or type. Additionally, it supports registration s, like registerService(String name, Object [implementation](/page/Implementation)), invoked during application initialization to bind concrete implementations to their interfaces. Internally, the locator often maintains a registry or —such as a hash map—to store these bindings, enabling efficient reuse of service instances and reducing overhead from repeated creations or external lookups. Services in the pattern are represented by interfaces or abstract classes that define the contracts for dependencies, ensuring that clients interact with abstractions rather than concrete classes. Concrete service implementations adhere to these contracts and are registered with the locator, frequently through an auxiliary Service Factory or initializer mechanism that handles instantiation logic, such as creating objects on demand if not already cached. This factory component abstracts the creation process, allowing the locator to focus on resolution while supporting for performance. Clients, the application components that depend on services (e.g., classes or elements), request dependencies exclusively through the Service Locator, avoiding direct instantiation or hardcoded references to service providers. This interaction enforces a clear separation, where clients remain agnostic to service locations and implementations. Configuration of the Service Locator typically occurs at startup via programmatic registration in code or declarative files like XML, facilitating by externalizing dependency mappings without altering client code. For instance, in EE contexts, services may be bound using configuration that abstracts vendor-specific details, enhancing portability across environments. These components collectively address dependency resolution by providing a structured registry that decouples service consumers from providers, though they introduce a global access point that requires careful management to avoid hidden dependencies.

Usage Flow

The usage of the service locator pattern begins with an initialization phase, typically during application bootstrap, where services are registered in a central registry or maintained by the locator. This registration often involves associating service keys (such as strings or identifiers) with concrete implementations, either directly or through an underlying lookup mechanism like JNDI in enterprise environments. For instance, in Java-based systems, an InitialContext is created to facilitate this setup, allowing services such as EJB homes or connection factories to be bound to the locator for later access. During , clients resolve by invoking a on the locator, such as getService( serviceName), passing the appropriate key to request the desired . The locator first checks its internal registry or for the ; if found, it returns the existing instance or a to it, thereby the client from direct instantiation or configuration details. If the is absent, the locator performs the necessary lookup or creation—abstracting complexities like JNDI operations—and returns the resolved , often caching it for subsequent requests. This flow enables dynamic retrieval without tight to locations or types. Error handling in the service locator pattern addresses cases where a requested service is unavailable, typically by throwing an exception to signal the failure, such as a ServiceLocatorException wrapping underlying lookup errors like NamingException in JNDI contexts. Some implementations may return null instead, allowing clients to handle the absence gracefully, though this can lead to runtime errors if dependencies are missing. Fallback mechanisms, like default service providers, can be incorporated but are not standard across all variants. Lifecycle management within the service locator involves strategies for instance persistence and disposal to balance performance and resource usage. Services are commonly cached in the locator's registry to promote singleton-like behavior, where a single instance is shared across requests to avoid repeated creation overhead, as seen in implementations using list-based or hashmap caches. For transient services requiring fresh instances per request, the locator can be configured to bypass caching and instantiate anew each time. Cleanup is generally handled at the application level, such as during shutdown, with the locator relying on garbage collection for unreferenced services, though explicit deregistration methods may be provided in advanced setups to release resources proactively.

Examples

Pseudocode Example

The service locator pattern typically involves a central registry that manages mappings between service identifiers (such as strings or keys) and concrete implementations of interfaces, allowing clients to retrieve services without direct dependencies on their creation or location details. In this example, services are registered explicitly in the locator's internal registry, which acts as a to store and reuse instances, thereby encapsulating lookup logic and promoting . The ServiceLocator is implemented as a to ensure a shared registry across the application.

Core Components in Pseudocode

The pattern revolves around the following abstract components:
  • Service Interface: Defines the contract for services.
    interface Service {
        void performAction();
    }
  • Concrete Service Implementation: A specific realization of the interface, such as a logger.
    class FileLogger implements Service {
        void performAction() {
            // Implementation: write to file
        }
    }
  • Service Locator: The central registry that handles registration and retrieval, implemented as a singleton.
    class ServiceLocator {
        private static ServiceLocator instance;
        private registry = new Map<String, Service>();  // Key-value store for bindings
    
        private ServiceLocator() {
            // Private constructor for singleton
        }
    
        static ServiceLocator getInstance() {
            if (instance == null) {
                instance = new ServiceLocator();
            }
            return instance;
        }
    
        void register(String key, Service implementation) {
            registry.put(key, implementation);  // Bind interface key to concrete instance
        }
    
        Service getService(String key) {
            if (registry.containsKey(key)) {
                return registry.get(key);  // Return cached instance
            }
            // Optional: Handle missing service (e.g., throw exception or return null)
            return null;
        }
    }

Service Registration

Registration establishes bindings in the locator's registry, where a service key (e.g., "Logger") maps to a implementation instance. For instance, during application initialization, the locator can be populated as follows:
ServiceLocator locator = ServiceLocator.getInstance();
[Service](/page/Service) fileLogger = new FileLogger();
locator.[register](/page/Register)("Logger", fileLogger);  // Maps "Logger" key to FileLogger instance
This allows multiple clients to access the same shared instance without knowing its type or creation details.

Client Usage

Clients retrieve services by key, receiving an reference that hides the :
ServiceLocator locator = ServiceLocator.getInstance();  // Retrieve shared [singleton](/page/Singleton) instance
Service logger = locator.getService("Logger");
if (logger != [null](/page/Null)) {
    logger.performAction();  // Calls FileLogger's [method](/page/Method)
}
This flow ensures that the client depends only on the locator and the , not on the specific or its instantiation.

Explanation of Bindings

Bindings in the service locator are managed through the registry, typically a hash map or similar , where keys represent abstract service identifiers (e.g., interface names) and values hold references to concrete objects. This mapping supports or pre-registration, with the locator optionally caching instances to avoid repeated creation, as seen in the getService method that checks the registry before lookup. Such bindings decouple service consumers from vendor-specific details like JNDI naming or creation.

Simple Diagram Description

A text-based representation of the class relationships and method calls resembles the following UML-like structure:
+---------------+       +-----------------+       +-----------------+
|   [Client](/page/Class)      | ----> | ServiceLocator  | <---- |   Registry      |
|               |       | -registry: Map  |       | (internal)      |
| -useService() |       | +getInstance()  |       | +put(key, impl) |
+---------------+       | +register(key,  |       | +get(key): impl |
                        |   impl): void   |       +-----------------+
                        | +getService(key)|               
                        |  ): Service     |
                        +-----------------+
                                 |
                                 | implements
                                 v
                        +-----------------+
                        |     Service     |
                        | +performAction()|
                        +-----------------+
                                 ^
                                 |
                        +-----------------+
                        |  FileLogger     |
                        | (concrete impl) |
                        +-----------------+
This diagram illustrates the client invoking the singleton locator's getService to obtain a Service reference, which binds to the FileLogger via the internal registry, following the usage flow where registration precedes retrieval.

Language-Specific Example

To illustrate the service locator pattern in practice, consider an implementation in Java using an in-memory registry for simplicity, as commonly described in design pattern literature. This example defines a PaymentService interface for processing payments, a concrete implementation, and a ServiceLocator class that maintains a registry of services via a HashMap. Services are registered at startup or dynamically, and retrieved with type-safe casting to avoid runtime errors where possible.
java
import java.util.HashMap;
import java.util.Map;

// Interface for the service
public interface PaymentService {
    void processPayment(double amount);
}

// Concrete implementation
public class CreditCardPaymentService implements PaymentService {
    @Override
    public void processPayment(double amount) {
        System.out.println("Processing credit card payment of $" + amount);
        // Implementation details, e.g., API call to payment gateway
    }
}

// Service Locator class
public class ServiceLocator {
    private static final Map<String, Object> services = new HashMap<>();

    // Register a service in the registry
    public static void registerService(String key, Object service) {
        services.put(key, service);
    }

    // Retrieve a service with type-safe casting
    @SuppressWarnings("unchecked")
    public static <T> T getService(String key, Class<T> serviceType) {
        Object service = services.get(key);
        if (service == null) {
            return null;  // Or throw a custom exception for missing service
        }
        try {
            return serviceType.cast(service);
        } catch (ClassCastException e) {
            throw new IllegalArgumentException("Service at key '" + key + "' is not of type " + serviceType.getName(), e);
        }
    }
}
This implementation builds on the dynamic service locator concept, where the HashMap acts as a central registry to decouple clients from direct instantiation. In a client class, such as an order processing component, the service is obtained via the locator during construction or method invocation, allowing flexible substitution without altering client code:
java
public class OrderProcessor {
    private final PaymentService paymentService;

    public OrderProcessor() {
        this.paymentService = ServiceLocator.getService("creditCard", PaymentService.class);
        if (this.paymentService == null) {
            throw new IllegalStateException("Payment service not registered");
        }
    }

    public void handleOrder(double amount) {
        paymentService.processPayment(amount);
    }
}

// Usage example (e.g., in main or bootstrap)
public class Main {
    public static void main(String[] args) {
        ServiceLocator.registerService("creditCard", new CreditCardPaymentService());
        OrderProcessor processor = new OrderProcessor();
        processor.handleOrder(100.0);
    }
}
The code compiles against standard Java (JDK 8+), requiring no external dependencies beyond the core libraries. At runtime, the getService method handles type mismatches via ClassCastException, which is caught and rethrown for clarity; ClassNotFoundException is not directly applicable here without dynamic class loading via Class.forName, but could arise in extensions using reflection for service instantiation. This approach provides benefits in environments mimicking Spring's service management without full dependency injection, such as legacy applications or lightweight containers, by centralizing service access and enabling caching to avoid repeated lookups. For variations, thread-safety can be added by replacing HashMap with ConcurrentHashMap for concurrent access or wrapping getService and registerService in synchronized blocks to prevent race conditions in multi-threaded scenarios.

Versus Dependency Injection

The service locator pattern operates on a pull model, in which client components explicitly request their required services from a central registry at runtime, often via method calls like ServiceLocator.getService(Type). In contrast, (DI) follows a push model, where dependencies are proactively supplied to components—typically through constructor parameters, methods, or injection—during object or , eliminating the need for lookups. This structural difference underscores a philosophical divergence: service locators centralize and empower clients to dependency resolution, while DI inverts , delegating responsibility for wiring components to an external assembler or , thereby enforcing separation of from use. Regarding coupling, the service locator conceals a component's dependencies from its interface, fostering a facade of simplicity but creating implicit global ties to the locator itself, which can lead to failures if services are unavailable and hinder static analysis of dependencies. DI counters this by declaring dependencies explicitly in the component's constructor or setters, reducing hidden s, enabling compile-time verification of requirements, and facilitating through straightforward substitution of mock implementations without altering the locator's state. Although both approaches support inversion in principle, DI's transparency aligns better with principles, particularly the , by making collaborations overt and testable. Service locators are lightweight and integrable into plain without external , relying on a simple static registry for service resolution. , however, typically leverages dedicated (IoC) containers for automated wiring, such as Spring's application context in ecosystems or .NET Core's built-in , which manage lifetimes, scopes, and registrations to streamline complex dependency graphs. documentation explicitly advises against service locator variants in .NET Core, favoring to avoid runtime resolution pitfalls and promote predictable behavior. Historically, DI emerged as the dominant alternative to service locators in the early 2000s, propelled by the advent of lightweight frameworks like (launched in 2003, emphasizing setter injection) and PicoContainer (2003, focusing on constructor injection), alongside Fowler's 2004 articulation of the pattern that highlighted its advantages over locator-based approaches in enterprise applications. This shift reflected broader adoption of IoC principles, originating from efforts like Apache Avalon's contextualized lookup in 1998 but evolving toward injection to address locator drawbacks in scalable systems.

Versus Factory Pattern

The service locator pattern emphasizes the discovery and retrieval of existing or pre-registered services from a central registry, clients from direct knowledge of service locations or implementations. In contrast, the factory pattern, a creational , focuses on encapsulating the logic for instantiating new objects based on specified criteria, allowing subclasses to alter the type of objects created without modifying client code. While the two patterns serve distinct purposes—lookup versus creation—hybrids exist where a service locator delegates instantiation to an internal when a requested is not already available in the registry, combining discovery with on-demand creation for more flexible management. Service locators are ideal for shared, long-lived services like caches or managers, where reuse across the application minimizes overhead, whereas factories suit transient, per-request objects such as database or components that require fresh instances. The factory pattern predates the service locator, originating in the foundational "" design patterns catalog published in 1994 to address object creation in object-oriented systems. The service locator pattern evolved later, gaining prominence in enterprise environments around 2001 through J2EE best practices to handle distributed in service-oriented architectures.

Evaluation

Advantages

The service locator pattern supports late binding, enabling dynamic selection and substitution of service implementations at , which proves advantageous in configurable applications where dependencies may need to adapt based on environmental factors or conditions. This flexibility allows developers to optimize application behavior without recompiling code, such as switching between service providers for load balancing or feature toggling. By centralizing access to services through a single locator object, the pattern simplifies client code, as classes no longer require extensive constructor parameters or methods for every ; instead, clients make straightforward requests to the locator. This reduces boilerplate and improves readability, particularly in systems with many interdependent components. In contrast to , it offers a more straightforward integration for legacy or incrementally refactored codebases where full might be disruptive. The centralized nature of the locator also streamlines service management, permitting global updates—such as caching strategies or reference replacements—without propagating changes across multiple client implementations, thereby enhancing in enterprise-scale applications. For instance, in distributed systems, it aggregates calls for lookups, improving overall performance by minimizing redundant JNDI operations.

Disadvantages

The service locator pattern introduces hidden dependencies, as classes do not explicitly declare their required services through constructors or interfaces, instead retrieving them implicitly at via the locator. This obscures the , making it difficult to statically analyze code and understand a class's prerequisites without inspecting its implementation details. Such hidden dependencies violate the principle of explicit dependencies, complicating code maintenance and refactoring, as developers must search through source code for locator calls rather than observing them in public APIs. As a form of global , the service locator—often implemented as a —creates shared mutable across the application, which can lead to concurrency issues in multithreaded environments if not carefully managed. This global accessibility encourages tight coupling to the locator itself, reducing component reusability, since classes become dependent on a specific locator instance that may not exist in other contexts. Testing with the service locator pattern presents significant challenges, as dependencies are resolved dynamically, requiring manual setup and teardown of the locator's registry in each test to mock or substitute services. This results in less isolated unit tests compared to , where dependencies are provided directly, and can defer errors from compile-time to runtime, such as failures when a required service is not registered. Consequently, test code becomes verbose and error-prone, undermining the pattern's utility for modular, testable designs. Since around 2010, the service locator pattern has been widely critiqued as an in modern , primarily because it undermines modularity and explicitness in favor of , which promotes better and easier verification. Influential analyses, such as those emphasizing its violation of encapsulation and principles, have solidified this view, positioning it as a solution that generates more long-term maintenance burdens than benefits.

Application Guidelines

When to Use

The service locator pattern is ideally suited for migrations, particularly in environments like J2EE applications, where it encapsulates complex JNDI lookups for accessing distributed components such as Enterprise JavaBeans (EJBs) and Java Message Service (JMS) queues or topics, thereby reducing code duplication and vendor dependencies without requiring a full architectural overhaul. This approach allows incremental integration of modern services into existing codebases, enabling repeated service access through a centralized that improves performance and uniformity. In simple applications without comprehensive dependency injection (DI) frameworks, the pattern provides a lightweight solution for decoupling clients from concrete service implementations, allowing runtime configuration of services via a central registry rather than hard-coded dependencies. For plugin architectures requiring dynamic , it supports runtime registration and retrieval of extensible components, such as varying providers identified through configuration, facilitating modular extensions without tight coupling. The pattern works best in small- to medium-scale applications where dependencies are limited and primarily shared across components, offering a straightforward to more elaborate setups when explicit service requests suffice. To enhance flexibility, integrate it with configuration files that map service interfaces to implementations, enabling easy swapping of providers at deployment time. However, in large systems, its reliance on global state can obscure dependencies, making it less suitable where is critical.

Common Pitfalls

One common pitfall in implementing the service locator pattern is its overuse as a replacement for (DI), which can lead to hidden dependencies scattered throughout the codebase, resembling that is difficult to trace and maintain. This occurs because classes directly invoke the locator to resolve dependencies at , obscuring the explicit wiring that DI provides via constructors or properties, often resulting in failures rather than compile-time errors. To mitigate this, the pattern should be restricted to registering and accessing only truly global services, such as or configuration managers, where widespread availability is essential and DI scoping would be impractical. Another frequent issue arises from ignoring concurrency concerns, as a basic service locator—often implemented as a static or registry—may not be thread-safe, leading to conditions when multiple threads to register or retrieve services simultaneously. For instance, unsynchronized access to an internal map or cache can corrupt the service registry or return inconsistent instances in multithreaded environments like web servers. Mitigation involves adding synchronization mechanisms, such as locks around registry operations or using to provide per-thread instances, ensuring safe concurrent access without blocking. Poor management of lookup keys is a subtle but pervasive problem, particularly when relying on string-based identifiers, which are prone to typos, refactoring breaks, or mismatches that cause silent failures or exceptions at . This lack of makes it challenging to enforce correct service resolution during or . To avoid this, developers should use enums or predefined constants as keys instead of raw strings, providing compile-time validation and improving code readability. Finally, memory leaks can occur if the service locator caches resolved services indefinitely without proper disposal, preventing garbage collection of unused instances in long-running applications. Static or singleton-based locators exacerbate this by holding references in global structures like dictionaries, leading to resource exhaustion over time. Implementing explicit disposal methods—such as a Release or Clear function that removes services from the cache when they are no longer needed—helps ensure timely cleanup and avoids accumulation of orphaned objects.

References

  1. [1]
    Service Locator Pattern and Java Implementation | Baeldung
    Mar 17, 2024 · The purpose of the Service Locator pattern is to return the service instances on demand. This is useful for decoupling service consumers ...
  2. [2]
    Inversion of Control Containers and the Dependency Injection pattern
    Jan 23, 2004 · The other pattern you can use to do this is Service Locator, and I'll discuss that after I'm done with explaining Dependency Injection.Setter Injection With Spring · Interface Injection · Service Locator Vs...
  3. [3]
    Core J2EE Patterns - Service Locator - Oracle
    The Service Locator abstracts the API lookup (naming) services, vendor dependencies, lookup complexities, and business object creation, and provides a simple ...<|control11|><|separator|>
  4. [4]
  5. [5]
    Service Locator - J2EE Design Patterns [Book] - O'Reilly
    In J2EE, service locators can be used to encapsulate interactions with the JNDI directory. The service factories are EJB home objects, or JMS connection ...
  6. [6]
    Service Locator Pattern - GeeksforGeeks
    Oct 31, 2023 · The service locator pattern is a design pattern used in software development to encapsulate the processes involved in obtaining a service with a strong ...
  7. [7]
    Service Locator is an Anti-Pattern - ploeh blog
    Feb 3, 2010 · Service Locator is a well-known pattern, and since it was described by Martin Fowler, it must be good, right?
  8. [8]
    Dependency injection in ASP.NET Core | Microsoft Learn
    Sep 18, 2024 · ASP.NET Core supports the dependency injection (DI) software design pattern, which is a technique for achieving Inversion of Control (IoC) between classes and ...Dependency injection into... · ASP.NET Core Blazor... · NET · Native AOT journey<|control11|><|separator|>
  9. [9]
    Inversion of Control History - PicoContainer
    Inversion of Control, as a term, was popularised in 1998 by Stefano Mazzocchi as consequence of trying to engineer a 'Java Apache Server Framework'.<|control11|><|separator|>
  10. [10]
    [PDF] Frameworks and Inversion of Control - UNIPI
    ServiceLocator – Pros and cons. • The Service Locator pattern succeeds in decoupling the TradeMonitor from the LimitDao. • Allows new components to be ...
  11. [11]
    Service Locator violates encapsulation
    ### Summary: How Service Locator Violates Encapsulation
  12. [12]
    Dependency Injection vs. Service Locator - Baeldung
    Mar 18, 2024 · In this tutorial, we'll review two patterns: Dependency Injection and Service Locator. They solve the same problem differently and often use terminology that ...
  13. [13]
    Service Locator violates SOLID - ploeh blog
    May 15, 2014 · Yet another reason to avoid the Service Locator anti-pattern is that it violates the principles of Object-Oriented Design.<|control11|><|separator|>
  14. [14]
    Service Locator - Game Programming Patterns
    it decouples code that needs a service from both who it is (the concrete implementation type) and where it ...
  15. [15]
    Service Locator Antipattern in Software Development - DevIQ
    Reduced code clarity: The Service Locator pattern can make it difficult to understand the dependencies between objects, as they are not explicitly defined.
  16. [16]
    Service Locator is not an Anti-Pattern - Jimmy Bogard
    Jan 11, 2022 · Design Patterns. Service Locator is not an ... Then we'll use service locator pattern to resolve and dispatch to one of the event handlers.
  17. [17]
    Memory Leaks using Dependency Injection with .NET Core
    Jan 2, 2021 · Service Locator Pattern. The Service Locator Pattern is an anti-pattern that exists when a class directly calls the DI Container to obtain ...Dependency Injection With... · Injecting Services Into A... · Scoping Services In A Hosted...
  18. [18]
    Castle Windsor: Avoid memory leaks by learning the underlying ...
    Apr 21, 2012 · If you are using Castle Windsor combined with service location you can get a lot of memory issues basically because the contract has no method for releasing ...