refactor(pricing): 优化优惠提供者初始化和依赖注入

- 使用 @Lazy 注解解决循环依赖问题
- 重构 DiscountDetectionServiceImpl 以延迟加载优惠提供者
- 移除构造函数中的直接依赖注入,改用 ObjectProvider
- 添加线程安全的提供者初始化机制
- 移除不必要的缓存注释
This commit is contained in:
2025-12-05 16:03:00 +08:00
parent 33c3a194ca
commit ee13ef09f7
4 changed files with 81 additions and 62 deletions

View File

@@ -7,8 +7,8 @@ import com.ycwl.basic.pricing.service.ICouponService;
import com.ycwl.basic.pricing.service.IDiscountProvider;
import com.ycwl.basic.pricing.service.IPriceBundleService;
import com.ycwl.basic.pricing.service.IProductConfigService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Component;
import java.math.BigDecimal;
@@ -20,13 +20,20 @@ import java.util.List;
*/
@Slf4j
@Component
@RequiredArgsConstructor
public class CouponDiscountProvider implements IDiscountProvider {
private final ICouponService couponService;
private final IProductConfigService productConfigService;
private final IPriceBundleService bundleService;
public CouponDiscountProvider(@Lazy ICouponService couponService,
@Lazy IProductConfigService productConfigService,
@Lazy IPriceBundleService bundleService) {
this.couponService = couponService;
this.productConfigService = productConfigService;
this.bundleService = bundleService;
}
@Override
public String getProviderType() {
return "COUPON";

View File

@@ -4,6 +4,7 @@ import com.ycwl.basic.pricing.dto.*;
import com.ycwl.basic.pricing.service.IDiscountDetectionService;
import com.ycwl.basic.pricing.service.IDiscountProvider;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@@ -20,21 +21,19 @@ import java.util.stream.Collectors;
@Service
public class DiscountDetectionServiceImpl implements IDiscountDetectionService {
private final ObjectProvider<IDiscountProvider> discountProviderProvider;
private final List<IDiscountProvider> discountProviders = new ArrayList<>();
private final Object providerInitLock = new Object();
private volatile boolean providersInitialized;
@Autowired
public DiscountDetectionServiceImpl(List<IDiscountProvider> providers) {
this.discountProviders.addAll(providers);
// 按优先级排序(优先级高的在前)
this.discountProviders.sort(Comparator.comparing(IDiscountProvider::getPriority).reversed());
log.info("注册了 {} 个优惠提供者: {}",
providers.size(),
providers.stream().map(IDiscountProvider::getProviderType).collect(Collectors.toList()));
public DiscountDetectionServiceImpl(ObjectProvider<IDiscountProvider> discountProviderProvider) {
this.discountProviderProvider = discountProviderProvider;
}
@Override
public List<DiscountInfo> detectAllAvailableDiscounts(DiscountDetectionContext context) {
initializeProvidersIfNecessary();
List<DiscountInfo> allDiscounts = new ArrayList<>();
for (IDiscountProvider provider : discountProviders) {
@@ -151,16 +150,22 @@ public class DiscountDetectionServiceImpl implements IDiscountDetectionService {
@Override
public void registerProvider(IDiscountProvider provider) {
if (provider != null && !discountProviders.contains(provider)) {
discountProviders.add(provider);
// 重新排序
discountProviders.sort(Comparator.comparing(IDiscountProvider::getPriority).reversed());
log.info("注册新的优惠提供者: {}", provider.getProviderType());
if (provider == null) {
return;
}
synchronized (providerInitLock) {
initializeProvidersIfNecessary();
if (!discountProviders.contains(provider)) {
discountProviders.add(provider);
discountProviders.sort(Comparator.comparing(IDiscountProvider::getPriority).reversed());
log.info("注册新的优惠提供者: {}", provider.getProviderType());
}
}
}
@Override
public List<IDiscountProvider> getAllProviders() {
initializeProvidersIfNecessary();
return new ArrayList<>(discountProviders);
}
@@ -168,6 +173,7 @@ public class DiscountDetectionServiceImpl implements IDiscountDetectionService {
* 查找指定类型的优惠提供者
*/
private IDiscountProvider findProvider(String providerType) {
initializeProvidersIfNecessary();
return discountProviders.stream()
.filter(provider -> providerType.equals(provider.getProviderType()))
.findFirst()
@@ -203,4 +209,22 @@ public class DiscountDetectionServiceImpl implements IDiscountDetectionService {
}
};
}
private void initializeProvidersIfNecessary() {
if (providersInitialized) {
return;
}
synchronized (providerInitLock) {
if (providersInitialized) {
return;
}
discountProviders.clear();
discountProviderProvider.stream().forEach(discountProviders::add);
discountProviders.sort(Comparator.comparing(IDiscountProvider::getPriority).reversed());
log.info("注册了 {} 个优惠提供者: {}",
discountProviders.size(),
discountProviders.stream().map(IDiscountProvider::getProviderType).collect(Collectors.toList()));
providersInitialized = true;
}
}
}

View File

@@ -97,13 +97,11 @@ public class PriceBundleServiceImpl implements IPriceBundleService {
}
@Override
// @Cacheable(value = "active-bundles")
public List<PriceBundleConfig> getActiveBundles() {
return bundleConfigMapper.selectActiveBundles();
}
@Override
// @Cacheable(value = "all-bundles")
public List<PriceBundleConfig> getAllBundles() {
return bundleConfigMapper.selectActiveBundles();
}

View File

@@ -30,13 +30,11 @@ public class ProductConfigServiceImpl implements IProductConfigService {
private final PriceTierConfigMapper tierConfigMapper;
@Override
// @Cacheable(value = "product-config", key = "#productType")
public List<PriceProductConfig> getProductConfig(String productType) {
return productConfigMapper.selectByProductType(productType);
}
@Override
// @Cacheable(value = "product-config", key = "#productType + '_' + #productId")
public PriceProductConfig getProductConfig(String productType, String productId) {
PriceProductConfig config = productConfigMapper.selectByProductTypeAndId(productType, productId);
if (config == null) {
@@ -46,7 +44,6 @@ public class ProductConfigServiceImpl implements IProductConfigService {
}
@Override
// @Cacheable(value = "tier-config", key = "#productType + '_' + #productId + '_' + #quantity")
public PriceTierConfig getTierConfig(String productType, String productId, Integer quantity) {
if (quantity == null || quantity <= 0) {
return null;
@@ -73,7 +70,6 @@ public class ProductConfigServiceImpl implements IProductConfigService {
}
@Override
// @Cacheable(value = "product-config", key = "#productType + '_' + #productId + '_' + #scenicId")
public PriceProductConfig getProductConfig(String productType, String productId, Long scenicId) {
if (scenicId == null) {
// 如果没有景区ID,使用原有逻辑
@@ -124,7 +120,6 @@ public class ProductConfigServiceImpl implements IProductConfigService {
}
@Override
// @Cacheable(value = "tier-config", key = "#productType + '_' + #productId + '_' + #quantity + '_' + #scenicId")
public PriceTierConfig getTierConfig(String productType, String productId, Integer quantity, Long scenicId) {
if (quantity == null || quantity <= 0) {
return null;
@@ -174,31 +169,26 @@ public class ProductConfigServiceImpl implements IProductConfigService {
}
@Override
// @Cacheable(value = "active-product-configs")
public List<PriceProductConfig> getActiveProductConfigs() {
return productConfigMapper.selectActiveConfigs();
}
@Override
// @Cacheable(value = "all-product-configs")
public List<PriceProductConfig> getAllProductConfigs() {
return productConfigMapper.selectActiveConfigs();
}
@Override
// @Cacheable(value = "tier-configs", key = "#productType")
public List<PriceTierConfig> getTierConfigs(String productType) {
return tierConfigMapper.selectByProductType(productType);
}
@Override
// @Cacheable(value = "tier-configs", key = "#productType + '_' + #productId")
public List<PriceTierConfig> getTierConfigs(String productType, String productId) {
return tierConfigMapper.selectByProductTypeAndId(productType, productId);
}
@Override
// @Cacheable(value = "all-tier-configs")
public List<PriceTierConfig> getAllTierConfigs() {
return tierConfigMapper.selectAllActiveConfigs();
}