Reputation: 1442
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);
}
}
Upvotes: 1
Views: 840
Reputation: 1442
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);
}
}
}
Upvotes: 0
Reputation: 31
Yes it's possible with the help of ServiceLocatorFactoryBean. Infact if we write Factory code to create implementation object then in that implementation class class if we inject any repository or other objects then it will throw exception. The reason is if user is created object then for those object spring is not allowing to inject the dependency. So better give the responsibility of creating implementation object by factory pattern using Spring. Try with ServiceLocatorFactoryBean
Upvotes: 0
Reputation: 713
This could be solved after creating two more bean in the configuration file. i.e.
@Bean
public PaymentService paymentServiceA(){
return new PaymentServiceImplA();
}
@Bean
public PaymentService paymentServiceB(){
return new PaymentServiceImplA();
}
and the returning bean should be :
@Bean
public PaymentService paymentService(){
if(condition == true)
return paymentServiceA();
else
return paymentServiceB();
}
Upvotes: 1