Spring может автоматически связывать различные реализации компонента, который реализует интерфейс I
, со свойством типа Map<String, I>
автоматически, где ключом является имя компонента и значение экземпляра компонента.Поскольку у вас уже есть перечисление для каждой реализации ProductHandler
, вы можете воспользоваться этим:
public enum ProductType {
ABC(ProductType.ABC_BEAN_NAME),
DEF(ProductType.DEF_BEAN_NAME);
public static final String ABC_BEAN_NAME = "abcProductHandler";
public static final String DEF_BEAN_NAME = "defProductHandler";
private String beanName;
ProductType(String beanName) { this.beanName = beanName; }
public String beanName() { return beanName; }
}
Затем определите свои различные реализации ProductHandler
либо в классе фабрики @Configuration
, либо с помощьюаннотации @Service
или @Component
:
@Service(ProductType.ABC_BEAN_NAME)
public class ABCProductHandler implements ProductHandler {
// ...
}
@Service(ProductType.DEF_BEAN_NAME)
public class DEFProductHandler implements ProductHandler {
// ...
}
Теперь, в вашем бобе ProductServiceImpl
, просто автоматически подключите Map<String, ProductHandler>
:
@Service
public class ProductServiceImpl implements ProductService {
private final Map<String, ProductHandler> productHandlersMap;
@Autowired
public ProductServiceImpl(Map<String, ProductHandler> productHandlersMap) {
this.productHandlersMap = productHandlersMap;
}
@Override
public ProductDetails calculateProductPrice(ProductType productType) {
productHandlersMap.get(productType.beanName()).calculate();
//..some otehr code goes here
return productDetails;
}
}
Таким образом, вы 'Позвольте Spring сделать всю работу по внедрению, и нет необходимости даже использовать метод @PostConstruct
.
Обратите внимание на использование productType.beanName()
внутри метода calculateProductPrice
.Это гарантирует, что вы используете правильный бин для расчета цены.