When I use spring framework, I find something that should be extract, for example, the service component (or member variable that is autowired). Code show as below:
abstract class Payment {
PaymentService paymentService;
void setPaymentService(OrderPaymentService paymentService) {
this.paymentService = paymentService;
}
}
@Component
public class CancelPayment extends Payment{
private OtherService2 otherSerivce2;
@Autowired
@Override
public void setPaymentService(PaymentService paymentService) {
super.setPaymentService(paymentService);
}
@Autowired
public CancelPayment(OtherService2 s2) {
this.otherSerivce2 = s2;
}
}
@Component
public class CreatePayment extends Payment{
private OtherService1 otherSerivce1;
@Autowired
@Override
public void setPaymentService(PaymentService paymentService) {
super.setPaymentService(paymentService);
}
@Autowired
public CreatePayment (OtherService1 s1) {
this.otherSerivce1 = s1;
}
}
As you can see, I use setter injection in each child class. Is this a better practice than autowire their parent's member variable?
Here are DI guidelines by Spring team:
A general guideline, which is recommended by Spring (see the sections on Constructor-based DI or Setter-based DI) is the following:
For mandatory dependencies or when aiming for immutability, use constructor injection
For optional or changeable dependencies, use setter injection
Avoid field injection in most cases
Now if you are sure you will use PaymentService I would suggest you to use constructor injection in your abstract class like this so object won't instantiate without dependency, also making it more immutable, clearer and thread safe:
abstract class Payment {
PaymentService paymentService;
public Payment(OrderPaymentService paymentService) {
this.paymentService = paymentService;
}
}
Then you can simply call super on your extended classes like this:
@Component
public class CreatePayment extends Payment{
private OtherService1 otherSerivce1;
@Autowired
public CreatePayment(PaymentService paymentService) {
super(paymentService);
}
}
This simply allows you to inject parent class using constructor (if paymentService is mandatory).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With