Backend Development 7 min read

Eliminate if‑else in Spring Boot with the Service Locator Pattern

This article demonstrates how to replace cumbersome if‑else logic in Spring Boot 3.4.2 by using the Service Locator pattern with ServiceLocatorFactoryBean, providing a clean way to select parsers for different file types through an enum, interface, and Spring‑managed beans.

Spring Full-Stack Practical Cases
Spring Full-Stack Practical Cases
Spring Full-Stack Practical Cases
Eliminate if‑else in Spring Boot with the Service Locator Pattern

1. Introduction

In many projects you need to invoke different implementations based on the input type, such as using separate parsers for XML, JSON, and CSV files. Traditional if‑else statements quickly become hard to maintain.

This article shows how to solve this problem in Spring Boot 3.4.2 using the Service Locator pattern.

2. Practical Example

2.1 Define Enum

public enum ContentType {
  JSON(TypeConstants.JSON_PARSER),
  XML(TypeConstants.XML_PARSER),
  CSV(TypeConstants.CSV_PARSER);

  private final String parserName;
  ContentType(String parserName) { this.parserName = parserName; }
  @Override
  public String toString() { return this.parserName; }

  public interface TypeConstants {
    String CSV_PARSER = "csvParser";
    String JSON_PARSER = "jsonParser";
    String XML_PARSER = "xmlParser";
  }
}

2.2 Define Parser Interface

public interface Parser {
  Map<String, Object> parse(Reader r);
}

2.3 Implement Parsers

@Component(TypeConstants.CSV_PARSER)
public class CSVParser implements Parser {
  @Override
  public Map<String, Object> parse(Reader r) {
    return Map.of("csv", "csv文件解析成功");
  }
}

@Component(TypeConstants.JSON_PARSER)
public class JSONParser implements Parser {
  @Override
  public Map<String, Object> parse(Reader r) {
    return Map.of("json", "json文件解析成功");
  }
}

@Component(TypeConstants.XML_PARSER)
public class XMLParser implements Parser {
  @Override
  public Map<String, Object> parse(Reader r) {
    return Map.of("xml", "xml文件解析成功");
  }
}

2.4 Define Service Locator Interface

public interface ParserFactory {
  Parser getParser(ContentType contentType);
}

2.5 Configure ServiceLocatorFactoryBean

@Configuration
public class ParserConfig {
  @Bean("parserFactory")
  ServiceLocatorFactoryBean serviceLocatorFactoryBean() {
    ServiceLocatorFactoryBean factoryBean = new ServiceLocatorFactoryBean();
    factoryBean.setServiceLocatorInterface(ParserFactory.class);
    return factoryBean;
  }
}

Spring generates a proxy for

ParserFactory

; the underlying

InvocationHandler

uses the first method argument to resolve the appropriate bean name.

2.6 Use Parser Service

@Service
public class ParserService {
  private final ParserFactory parserFactory;
  public ParserService(ParserFactory parserFactory) { this.parserFactory = parserFactory; }
  public Map<String, Object> getData(ContentType contentType) {
    Parser parser = parserFactory.getParser(contentType);
    InputStreamReader reader = null; // replace with actual source
    return parser.parse(reader);
  }
}

2.7 Test Runner

@Component
public class ParserRunner implements CommandLineRunner {
  private final ParserService parserService;
  public ParserRunner(ParserService parserService) { this.parserService = parserService; }
  @Override
  public void run(String... args) throws Exception {
    Map<String, Object> data = parserService.getData(ContentType.CSV);
    System.err.println(data);
    data = parserService.getData(ContentType.JSON);
    System.err.println(data);
    data = parserService.getData(ContentType.XML);
    System.err.println(data);
  }
}

Running the application prints the parsing results for CSV, JSON and XML.

Service Locator workflow diagram
Service Locator workflow diagram
Console output of parser results
Console output of parser results

Conclusion

The Service Locator pattern removes the client’s direct dependency on concrete implementations. As Martin Fowler puts it, “the basic idea is to have an object that knows how to obtain all services an application may need.”

JavaSpring BootDesign Patterndependency injectionService Locator
Spring Full-Stack Practical Cases
Written by

Spring Full-Stack Practical Cases

Full-stack Java development with Vue 2/3 front-end suite; hands-on examples and source code analysis for Spring, Spring Boot 2/3, and Spring Cloud.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.