Programming & Development / April 19, 2025

Choosing Different Interface Implementations Based on Class Type Using @Bean Annotation in Spring

Spring @Bean Annotation Interface Implementation Runtime Dependency Injection Map Selector

1. Introduction

In Spring, it's often necessary to choose different interface implementations based on the class type at runtime. This can be especially useful in scenarios where your application needs to behave differently depending on the class type. You can achieve this by leveraging the @Bean annotation and Spring's powerful dependency injection. This method is clean, easily extendable, and provides flexibility for managing various implementations.

2. Code Explanation

Below, we walk through an example of how to use Spring's @Bean annotation to select different interface implementations based on the class type at runtime.

2.1. Define Your Interface and Implementations

First, you define the interface and its different implementations.

java

public interface MyInterface {
    void doSomething();
}

@Component
public class ImplementationA implements MyInterface {
    @Override
    public void doSomething() {
        System.out.println("Implementation A");
    }
}

@Component
public class ImplementationB implements MyInterface {
    @Override
    public void doSomething() {
        System.out.println("Implementation B");
    }
}
  • Explanation: Here, we define MyInterface with a method doSomething. We then create two implementations: ImplementationA and ImplementationB, which print different messages when doSomething() is called. Both are marked as @Component, which makes them Spring beans.

2.2. Create a Configuration Class with Bean Definitions

Next, we create a Spring @Configuration class where we define a Map that maps class types to their corresponding interface implementations. The beans are registered using the @Bean annotation.

java

@Configuration
public class MyConfig {

    @Bean
    public Map<Class<?>, MyInterface> implementationMap(ImplementationA implementationA, ImplementationB implementationB) {
        Map<Class<?>, MyInterface> map = new HashMap<>();
        map.put(ClassA.class, implementationA);
        map.put(ClassB.class, implementationB);
        return map;
    }
}
  • Explanation: In this configuration class, the implementationMap method creates a Map that associates each class type (ClassA, ClassB) with its corresponding implementation (ImplementationA, ImplementationB). This map will be used to select the appropriate implementation later on.

2.3. Inject the Map and Select the Implementation

Now we create the InterfaceSelector class that will be responsible for selecting the correct implementation based on the class type.

java

@Component
public class InterfaceSelector {

    private final Map<Class<?>, MyInterface> implementationMap;

    @Autowired
    public InterfaceSelector(Map<Class<?>, MyInterface> implementationMap) {
        this.implementationMap = implementationMap;
    }

    public MyInterface selectImplementation(Object obj) {
        MyInterface implementation = implementationMap.get(obj.getClass());
        if (implementation == null) {
            throw new IllegalArgumentException("Unsupported class type");
        }
        return implementation;
    }
}
  • Explanation: The InterfaceSelector class is injected with the implementationMap. It has a method selectImplementation that looks up the map for the correct implementation based on the class type of the passed object. If the class type isn't found, it throws an exception.

2.4. Using the Selector in Your Application

Now that we have our InterfaceSelector, we can use it in a service to select the correct implementation and perform an action.

java

@Component
public class MyService {

    private final InterfaceSelector interfaceSelector;

    @Autowired
    public MyService(InterfaceSelector interfaceSelector) {
        this.interfaceSelector = interfaceSelector;
    }

    public void process(Object obj) {
        MyInterface implementation = interfaceSelector.selectImplementation(obj);
        implementation.doSomething();
    }
}
  • Explanation: The MyService class is injected with the InterfaceSelector. It uses selectImplementation to get the appropriate implementation and calls doSomething() on it. This allows the MyService class to work with any object type that has an associated interface implementation.

2.5. Example Usage

Finally, we see how the application might be set up and used:

java

@SpringBootApplication
public class MyApplication {

    public static void main(String[] args) {
        ApplicationContext context = SpringApplication.run(MyApplication.class, args);
        MyService myService = context.getBean(MyService.class);

        ClassA classA = new ClassA();
        myService.process(classA);  // Output: Implementation A

        ClassB classB = new ClassB();
        myService.process(classB);  // Output: Implementation B
    }
}
  • Explanation: In this example, we use SpringApplication.run to start the Spring context and obtain the MyService bean. We then pass objects of ClassA and ClassB to myService.process(), which selects and uses the correct implementation based on the class type.

3. Summary

In this approach, we use Spring’s @Bean annotation to define a map of class types and their corresponding interface implementations. The InterfaceSelector class is responsible for selecting the appropriate implementation at runtime. This method is efficient, clean, and takes full advantage of Spring’s dependency injection system.

By using this technique, you can easily manage different implementations for different class types in a Spring application, allowing for flexible and maintainable code. This approach can be particularly useful in scenarios where you have a variety of objects with different behaviors, and you want to select the appropriate behavior dynamically at runtime.


Comments

No comments yet

Add a new Comment

NUHMAN.COM

Information Technology website for Programming & Development, Web Design & UX/UI, Startups & Innovation, Gadgets & Consumer Tech, Cloud Computing & Enterprise Tech, Cybersecurity, Artificial Intelligence (AI) & Machine Learning (ML), Gaming Technology, Mobile Development, Tech News & Trends, Open Source & Linux, Data Science & Analytics

Categories

Tags

©{" "} Nuhmans.com . All Rights Reserved. Designed by{" "} HTML Codex