Home

If-else Optimization of Bean Autowiring

Li

Li Wei

August 17, 20254 min read

Title: Optimizing If‑else with Bean Autowiring

Introduction

In the Spring framework we often encounter code like this:

@Resource
private Map<String, ConditionHandler> conditionHandlerMap;

The line looks simple, but it hides the powerful mechanisms of the Spring IoC container. This article delves into how Spring automatically injects all implementations of ConditionHandler into this map.

Background

Business scenario:

Suppose we have a conditional‑evaluation system that needs to support various operators: equals, greaterThan, lessThan, etc. A traditional approach might look like this:

if (op.equals("equals")) { … }
else if (op.equals("greaterThan")) { … }
else if (op.equals("lessThan")) { … }

Optimized solution:

Use the Strategy pattern together with Spring dependency injection:

@Resource
private Map<String, ConditionHandler> conditionHandlerMap;

Core question: How does Spring know which beans to put into this map?

Core Interface Design

Strategy interface:

public interface ConditionHandler {
    boolean handle(Object left, Object right);
}

Concrete strategy implementations:

@Component
public class Equals implements ConditionHandler { … }

@Component
public class GreaterThan implements ConditionHandler { … }

@Component
public class LessThan implements ConditionHandler { … }

Spring Container Startup Process

Phase 1: Component scanning

Scanning results:

  • Equals class is annotated with @Component
  • GreaterThan class is annotated with @Component
  • LessThan class is annotated with @Component

Phase 2: Bean definition registration

Bean‑name generation rules:

  • Equalsequals (class name with the first letter lower‑cased)
  • GreaterThangreaterThan
  • LessThanlessThan

Registration result:

BeanDefinition for equals → class Equals
BeanDefinition for greaterThan → class GreaterThan
BeanDefinition for lessThan → class LessThan

Dependency‑Injection Trigger Mechanism

When Spring creates an instance of RouteLabelConditionProcessor, the internal flow is:

  1. Instantiate RouteLabelConditionProcessor
  2. Scan all fields of the class and find the @Resource annotation
  3. Resolve the field type: Map<String, ConditionHandler>
  4. Trigger the dependency‑injection logic

Dependency descriptor:

Field: conditionHandlerMap
Type: java.util.Map<java.lang.String, com.example.ConditionHandler>
Annotation: @Resource

Core Algorithm for Map Dependency Resolution

Finding candidate beans:

Spring looks for all beans whose type matches ConditionHandler.

Type‑matching process:

  1. Examine the generic type of the map (ConditionHandler).
  2. Collect every bean that implements this interface.

Matching example:

  • Equals → matches
  • GreaterThan → matches
  • LessThan → matches

Final map assembly:

After the above steps, Spring builds a map like:

{
    "equals"      : equalsBean,
    "greaterThan": greaterThanBean,
    "lessThan"   : lessThanBean
}

Runtime Usage

Strategy selection:

ConditionHandler handler = conditionHandlerMap.get(operator);
boolean result = handler.handle(left, right);

Performance advantages:

  • Map lookup: O(1) time complexity
  • Avoids if‑else: No matter how many operators exist, lookup time stays constant
  • Type safety: Compile‑time guarantees correct types

FAQ

Q1: What happens if two implementation classes have the same name?

A: Spring throws a BeanDefinitionStoreException because of a bean‑name conflict.

Q2: Can I customize the bean name?

A: Yes, specify a name with @Component("customName").

Q3: Must the map’s key be the bean name?

A: Yes, by default Spring uses the bean name as the map key.

Q4: What if no implementation classes are found?

A: If the field is annotated with @Resource(required=true) (the default), Spring throws a NoSuchBeanDefinitionException.

Summary

Spring’s map‑dependency‑injection mechanism works through the following steps:

  1. Scanning phase: Detect all classes annotated with @Component.
  2. Registration phase: Register each class as a BeanDefinition.
  3. Resolution phase: Analyze the generic information of the Map.
  4. Matching phase: Find all beans that implement the ConditionHandler interface.
  5. Assembly phase: Build the Map<String, ConditionHandler>.
  6. Injection phase: Inject the map into the target field.

This mechanism dramatically improves code maintainability and extensibility, showcasing the elegance of Spring’s design.


Originally written by Li Wei (李唯_) and published in Chinese on 后端技术栈全书 (Full-Stack Backend Engineering). Translated and adapted for DriftSeas with permission.

Keep reading

More related articles from DriftSeas.