If-else Optimization: Dynamic Bean Loading
Li Wei
Title: Optimizing If‑Else with Dynamic Bean Loading
Introduction
When dealing with complex business logic, we often need to execute different processing paths based on various conditions. Traditional if‑else or switch statements can make the code verbose and hard to maintain. This article, based on the ConditionHandler interface from a real project (see reference), explores two strategy‑pattern implementations: Spring’s automatic injection of a Map and dynamic bean loading.
Background
In a routing‑tag condition evaluation system, we must support multiple operators such as greater‑than, less‑than, equal, range, etc. Each operator has its own calculation logic, and the appropriate handler must be selected dynamically according to the operator type.
Core interface design:
Solution 1: Bean Auto‑Wiring
Implementation
Handler implementation example:
How It Works
Assembly process:
- When the Spring container starts, it scans all classes annotated with
@Component. - For classes that implement the
ConditionHandlerinterface, Spring instantiates them and registers them as beans. - When injecting
Map, Spring looks up all beans of typeConditionHandler. - It uses the bean name as the key and the bean instance as the value, builds a
Map, and injects it.
Pros and Cons
Advantages
- Concise code; relies on Spring’s automatic injection.
- No need to maintain a manual registry.
- Adding a new handler only requires creating a new class and annotating it with
@Component.
Disadvantages
- Tied to the Spring container; cannot be used in non‑Spring environments.
- Cannot be used in static contexts.
- Handlers cannot be added or removed at runtime.
Solution 2: Dynamic Bean Loading
Aware Interface System
Spring provides a set of Aware interfaces that let a bean obtain specific framework objects from the Spring container.
Aware is a marker interface indicating that a bean is eligible to be notified by the container via callback methods. Spring offers several Aware interfaces:
BeanNameAware– obtain the bean nameApplicationContextAware– obtain theApplicationContextBeanFactoryAware– obtain theBeanFactoryEnvironmentAware– obtain theEnvironment
BeanNameAware
Interface definition:
How it works:
During a bean’s lifecycle, Spring calls the methods of various Aware interfaces. The invocation timing for BeanNameAware is as follows:
Source code analysis:
In Spring’s AbstractAutowireCapableBeanFactory there is a dedicated method for handling Aware interfaces:
Dynamic Loading Implementation
Enhanced interface design:
Abstract base‑class implementation:
Dynamic registration table design:
Concrete handler implementation:
Loading Process Analysis
Spring container startup phase:
Bean instantiation phase:
Automatic registration process:
Usage phase process:
Dynamic Extension Capability
Add handlers at runtime:
- Handler management interface:
Thread‑Safety
Since the registry performs bean operations, we must consider concurrent access to the map and potential resource contention:
Comparison of the Two Approaches
| Feature | Spring Auto‑Wired Map | Dynamic Bean Loading |
|---|---|---|
| Code volume | Less | More |
| Spring dependency | Strong | Weak |
| Use in static context | Not supported | Supported |
| Dynamic add/remove | Not supported | Supported |
| Concurrency handling | Spring‑managed | Handled manually |
| Extension | Add class + annotation | Add class + annotation + registration |
| Technical complexity | Low | Medium |
| Runtime monitoring | Difficult | Easy |
Typical use cases
When to prefer Spring auto‑wired Map:
- Pure Spring applications
- Relatively fixed number of handlers
- No need to use in static contexts
- Preference for concise code
When to prefer dynamic bean loading:
- Mixed‑architecture applications
- Need to operate in non‑Spring environments
- Need to add or remove handlers at runtime
- Need to use in static contexts
- Need runtime monitoring and management
Conclusion
The dynamic bean loading approach leverages Spring’s BeanNameAware mechanism to automatically discover and register handlers. Compared with the simple Spring auto‑wired Map, it offers greater flexibility and extensibility, making it especially suitable for complex business scenarios that require dynamic strategy management.
Key technical points
- BeanNameAware callback mechanism: enables beans to self‑register
- Static registry design: supports use outside Spring
- Thread‑safety guarantees: uses
ConcurrentHashMap - Dynamic extensibility: add/remove handlers at runtime
- Robust exception handling: ensures system stability
Whichever solution you choose, both effectively eliminate large amounts of if‑else code, improve maintainability and extensibility, and truly realize the Open/Closed Principle.
Originally written by Li Wei (李唯_) and published in Chinese on 后端技术栈全书 (Full-Stack Backend Engineering). Translated and adapted for DriftSeas with permission.