Search code examples
javaspringspring-bootdependency-injectionfactory-pattern

Factory method getting new instance from DI Container


I'm trying to create a factory method in a Java Spring boot application. But instead of manually instantiating an object I would like to get it from DI container. Is that possible?

public interface PaymentService {
    public Payment createPayment(String taskId);
}

public class PaymentServiceImplA implements PaymentService {
    private JobService jobService;
    private ApplicationService applicationService;
    private UserService userService;
    private WorkService workService;

    @Inject
    public PaymentServiceImplA(JobService jobService, UserService userService, WorkService workService,
        ApplicationService applicationService) {
        this.jobService = jobService;
        this.applicationService = applicationService;
        this.userService = userService;
        this.workService = workService;
        //removed other constructor injected dependencies
    }
}

Getting error "No qualifying bean of type 'com.test.mp.service.PaymentServiceImplA' available" when getBean method is called.

@Configuration
public class PaymentFactory {

    private ApplicationContext applicationContext;

    @Inject
    public PaymentFactory(ApplicationContext applicationContext) {      
        this.applicationContext = applicationContext;
    }

    @Bean
    public PaymentService paymentService(){
        //Using getBean method doesn't work, throws error mentioned above             
        if(condition == true) 
            return applicationContext.getBean(PaymentServiceImplA.class);
        else
            return applicationContext.getBean(PaymentServiceImplB.class);

    }
}

Solution

  • This is how I ended up solving this for now. By injecting the bean method with dependencies required to instantiate the implementation objects.

    @Configuration
    public class PaymentFactory {
    
        //private ApplicationContext applicationContext;
    
        public PaymentFactory() {      
            //this.applicationContext = applicationContext;
        }
    
        @Bean
        public PaymentService paymentService(JobService jobService, UserService userService
        , WorkService workService, ApplicationService applicationService){
    
            if(condition == true){
                return new PaymentServiceImplA(jobService, userService, workService,
        applicationService);
            }
            else {
                return new PaymentServiceImplB(jobService, userService, workService,
        applicationService);
            }
        }
    }