Search code examples
springspring-bootdependency-injectioninversion-of-controlspring-boot-starter

How can I create a bean of a class that needs other classes in the constructor?


I am trying to create my own spring-boot-starter. I have a class A that takes as arguments in the constructor classes B, C and an interface D, and I want to create in the autoconfiguration class a method annotated with @Bean that returns an instance of class A.

I tried to create methods annotated with @Bean for the other three needed classes (commented code of the image), so when this three are created (B, C, D), then maybe A bean could be created, using @ConditionalOnBean annotation. But in this way I do not know how to return a bean of D that is an interface instead of a class as happens with B and C that works well.

//Imports and package statement

@Configuration
@ConditionalOnClass(A.class)
public class AutoConfig {

//  @Bean
//  @ConditionalOnMissingBean
//  public B BFactory() {
//      return new B(); // It works
//  }
//  
//  @Bean
//  @ConditionalOnMissingBean
//  public C CFactory() {
//      return new C(); // It works
//  }
//  
//  @Bean
//  @ConditionalOnMissingBean
//  public D DFactory() {
//      return new D(); // I cannot do this because D is an interface
//  }
//  
    @Bean
    //@ConditionalOnBean(A.class, B.class, C.class)
    @ConditionalOnMissingBean
    public A AFactory() {
        return new A(?(B.class), ?(C.class), ?(D.class));
    }
}



//Imports and package statement

@Component
public class A {

    private B attribute1;
    private C attribute2;
    private D attribute3;

    @Autowired
    public A(B b, C c, D d) {
        this.b = b;
        this.c = c;
        this.d = d;
    }

    //Methods...
}

Summarizing, how can I create a bean of A given the need of B, C and D to create it and D being an interface?

Thank you so much for your help!


Solution

  • @Bean and @Component both create Spring Bean. So you need to declare Bean of A in configuration class. Create Bean of B,C and D only. It will automatically injected into A using @Autowired.
    You need to create some Implement of D interface. If it is coning from any other jar where it already has been declared as Spring Bean, then you don’t need to declare again in configuration, it will automatically get injected.

    Otherwise you can also do below for D:

    return new D() { 
        // provide implementation of abstract method if any
    };