Spring Boot
@Bean annotation
abstract class
Java
dependency injection

How to create a bean using Bean annotation in Spring Boot for abstract class?

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

You cannot instantiate an abstract class directly, so Spring cannot create a bean from the abstract class itself alone. What you can do is declare a @Bean method whose return type is the abstract class and have that method return a concrete subclass instance. That is the usual solution when you want the rest of the application to depend on the abstract type.

The Key Rule

This does not work conceptually:

  • abstract class as the thing Spring should instantiate directly

This does work:

  • abstract class as the exposed bean type
  • concrete implementation as the object actually returned

That distinction is the entire answer.

Example With A Concrete Subclass

Suppose you have an abstract service:

java
1public abstract class PaymentService {
2    public abstract String providerName();
3
4    public String process() {
5        return "Processing with " + providerName();
6    }
7}

And a concrete implementation:

java
1public class StripePaymentService extends PaymentService {
2    @Override
3    public String providerName() {
4        return "Stripe";
5    }
6}

Now expose it from a configuration class:

java
1import org.springframework.context.annotation.Bean;
2import org.springframework.context.annotation.Configuration;
3
4@Configuration
5public class PaymentConfig {
6
7    @Bean
8    public PaymentService paymentService() {
9        return new StripePaymentService();
10    }
11}

Spring manages the returned StripePaymentService instance, but any injection point can depend on PaymentService.

Injecting The Abstract Type

Once the bean is registered, inject the abstract type normally.

java
1import org.springframework.stereotype.Service;
2
3@Service
4public class CheckoutService {
5    private final PaymentService paymentService;
6
7    public CheckoutService(PaymentService paymentService) {
8        this.paymentService = paymentService;
9    }
10
11    public void checkout() {
12        System.out.println(paymentService.process());
13    }
14}

This is exactly why returning the abstract type from the @Bean method is useful. The rest of the application depends on the abstraction, not the concrete class.

You Can Also Use Constructor Arguments

A @Bean method can build the concrete subclass with dependencies.

java
1public class StripePaymentService extends PaymentService {
2    private final String apiKey;
3
4    public StripePaymentService(String apiKey) {
5        this.apiKey = apiKey;
6    }
7
8    @Override
9    public String providerName() {
10        return "Stripe-" + apiKey;
11    }
12}
java
1import org.springframework.context.annotation.Bean;
2import org.springframework.context.annotation.Configuration;
3
4@Configuration
5public class PaymentConfig {
6
7    @Bean
8    public PaymentService paymentService() {
9        return new StripePaymentService("test-key");
10    }
11}

This is common when the implementation class is not annotated with @Component or when you want full construction control.

What About Anonymous Subclasses

Technically, you can return an anonymous subclass from a @Bean method.

java
1@Bean
2public PaymentService paymentService() {
3    return new PaymentService() {
4        @Override
5        public String providerName() {
6            return "Anonymous";
7        }
8    };
9}

This works, but it is usually a poor long-term design. Anonymous subclasses are harder to test, document, and reuse. Prefer a named concrete implementation unless the logic is trivial and truly local.

Multiple Implementations Need Qualifiers

If you define more than one bean of the same abstract type, plain injection becomes ambiguous.

java
1@Bean
2public PaymentService stripePaymentService() {
3    return new StripePaymentService();
4}
5
6@Bean
7public PaymentService paypalPaymentService() {
8    return new PaypalPaymentService();
9}

Now Spring needs help choosing one. Use @Qualifier or @Primary depending on the design.

When @Bean Is Better Than @Component

Use @Bean when:

  • the implementation class is from a third-party library
  • construction logic is conditional or customized
  • you want to expose an abstract type while choosing the implementation in configuration

Use @Component when the concrete class is yours and straightforward to discover by component scanning.

Common Pitfalls

  • Expecting Spring to instantiate the abstract class itself.
  • Returning null or an incomplete placeholder from the @Bean method.
  • Creating multiple beans of the same abstract type without qualifiers or a primary bean.
  • Using anonymous subclasses when a named implementation would be clearer.
  • Confusing the bean's exposed type with the actual class being instantiated.

Summary

  • Spring cannot instantiate an abstract class directly.
  • A @Bean method can return the abstract type while creating a concrete subclass instance.
  • This allows the rest of the application to depend on the abstraction.
  • Use qualifiers or @Primary if multiple implementations exist.
  • Prefer named concrete classes over anonymous subclasses for maintainability.

Course illustration
Course illustration

All Rights Reserved.