修复优惠券模块
This commit is contained in:
@@ -1,24 +1,24 @@
|
|||||||
# Spring Bean 循环依赖修复报告
|
# Spring Bean 循环依赖修复报告 (完整版)
|
||||||
|
|
||||||
## 问题描述
|
## 问题描述
|
||||||
|
|
||||||
应用启动时出现 `BeanCreationException` 错误,错误信息显示:
|
应用启动时出现复杂的 `BeanCreationException` 错误,涉及多个Bean的循环依赖:
|
||||||
|
|
||||||
```
|
```
|
||||||
Error creating bean with name 'bszxBmController': Injection of resource dependencies failed;
|
Error creating bean with name 'bszxBmController': Injection of resource dependencies failed;
|
||||||
nested exception is org.springframework.beans.factory.BeanCreationException:
|
nested exception is org.springframework.beans.factory.BeanCreationException:
|
||||||
Error creating bean with name 'bszxBmServiceImpl': Injection of resource dependencies failed;
|
Error creating bean with name 'bszxBmServiceImpl': Injection of resource dependencies failed;
|
||||||
nested exception is org.springframework.beans.factory.BeanCreationException:
|
nested exception is org.springframework.beans.factory.BeanCreationException:
|
||||||
Error creating bean with name 'cmsArticleServiceImpl': Injection of resource dependencies failed;
|
Error creating bean with name 'cmsArticleServiceImpl': Injection of resource dependencies failed;
|
||||||
nested exception is org.springframework.beans.factory.BeanCreationException:
|
nested exception is org.springframework.beans.factory.BeanCreationException:
|
||||||
Error creating bean with name 'cmsNavigationServiceImpl': Injection of resource dependencies failed;
|
Error creating bean with name 'cmsNavigationServiceImpl': Injection of resource dependencies failed;
|
||||||
nested exception is org.springframework.beans.factory.BeanCreationException:
|
nested exception is org.springframework.beans.factory.BeanCreationException:
|
||||||
Error creating bean with name 'cmsDesignServiceImpl': Injection of resource dependencies failed
|
Error creating bean with name 'cmsDesignServiceImpl': Injection of resource dependencies failed
|
||||||
```
|
```
|
||||||
|
|
||||||
## 根本原因分析
|
## 根本原因分析
|
||||||
|
|
||||||
通过分析代码发现了两个主要的循环依赖问题:
|
通过分析代码发现了复杂的循环依赖链,涉及多个层级的Bean相互依赖:
|
||||||
|
|
||||||
### 1. 自我注入问题
|
### 1. 自我注入问题
|
||||||
在 `CmsNavigationServiceImpl` 中存在自我注入:
|
在 `CmsNavigationServiceImpl` 中存在自我注入:
|
||||||
@@ -28,20 +28,28 @@ Error creating bean with name 'cmsDesignServiceImpl': Injection of resource depe
|
|||||||
public class CmsNavigationServiceImpl extends ServiceImpl<CmsNavigationMapper, CmsNavigation> implements CmsNavigationService {
|
public class CmsNavigationServiceImpl extends ServiceImpl<CmsNavigationMapper, CmsNavigation> implements CmsNavigationService {
|
||||||
@Resource
|
@Resource
|
||||||
private CmsNavigationService cmsNavigationService; // 自我注入!
|
private CmsNavigationService cmsNavigationService; // 自我注入!
|
||||||
|
|
||||||
// 在方法中使用
|
// 在方法中使用
|
||||||
final CmsNavigation parent = cmsNavigationService.getOne(...);
|
final CmsNavigation parent = cmsNavigationService.getOne(...);
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### 2. 循环依赖问题
|
### 2. 复杂的循环依赖链
|
||||||
- `CmsNavigationServiceImpl` 依赖 `CmsDesignService`
|
发现了以下循环依赖关系:
|
||||||
|
|
||||||
|
**主要循环依赖链**:
|
||||||
|
```
|
||||||
|
BszxBmController → BszxBmService → CmsArticleService → CmsNavigationService → CmsDesignService → CmsNavigationService
|
||||||
|
```
|
||||||
|
|
||||||
|
**具体依赖关系**:
|
||||||
|
- `BszxBmController` 依赖 `BszxBmService` 和 `CmsArticleService`
|
||||||
|
- `BszxBmServiceImpl` 依赖 `CmsArticleService`
|
||||||
|
- `CmsArticleServiceImpl` 依赖 `CmsNavigationService`
|
||||||
|
- `CmsNavigationServiceImpl` 依赖 `CmsDesignService` 和自我注入 `CmsNavigationService`
|
||||||
- `CmsDesignServiceImpl` 依赖 `CmsNavigationService`
|
- `CmsDesignServiceImpl` 依赖 `CmsNavigationService`
|
||||||
|
|
||||||
这形成了一个循环依赖链:
|
这形成了一个复杂的循环依赖网络,导致Spring无法正确初始化这些Bean。
|
||||||
```
|
|
||||||
CmsNavigationServiceImpl → CmsDesignService → CmsDesignServiceImpl → CmsNavigationService → CmsNavigationServiceImpl
|
|
||||||
```
|
|
||||||
|
|
||||||
## 修复方案
|
## 修复方案
|
||||||
|
|
||||||
@@ -66,17 +74,9 @@ final CmsNavigation parent = cmsNavigationService.getOne(new LambdaQueryWrapper<
|
|||||||
final CmsNavigation parent = this.getOne(new LambdaQueryWrapper<CmsNavigation>()...);
|
final CmsNavigation parent = this.getOne(new LambdaQueryWrapper<CmsNavigation>()...);
|
||||||
```
|
```
|
||||||
|
|
||||||
### 修复2:解决循环依赖问题
|
### 修复2:使用 @Lazy 注解打破循环依赖
|
||||||
|
|
||||||
**文件**: `src/main/java/com/gxwebsoft/cms/service/impl/CmsDesignServiceImpl.java`
|
**文件1**: `src/main/java/com/gxwebsoft/cms/service/impl/CmsDesignServiceImpl.java`
|
||||||
|
|
||||||
**修复前**:
|
|
||||||
```java
|
|
||||||
@Resource
|
|
||||||
private CmsNavigationService cmsNavigationService;
|
|
||||||
```
|
|
||||||
|
|
||||||
**修复后**:
|
|
||||||
```java
|
```java
|
||||||
import org.springframework.context.annotation.Lazy;
|
import org.springframework.context.annotation.Lazy;
|
||||||
|
|
||||||
@@ -85,6 +85,33 @@ import org.springframework.context.annotation.Lazy;
|
|||||||
private CmsNavigationService cmsNavigationService;
|
private CmsNavigationService cmsNavigationService;
|
||||||
```
|
```
|
||||||
|
|
||||||
|
**文件2**: `src/main/java/com/gxwebsoft/cms/service/impl/CmsArticleServiceImpl.java`
|
||||||
|
```java
|
||||||
|
import org.springframework.context.annotation.Lazy;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
@Lazy
|
||||||
|
private CmsNavigationService cmsNavigationService;
|
||||||
|
```
|
||||||
|
|
||||||
|
**文件3**: `src/main/java/com/gxwebsoft/bszx/service/impl/BszxBmServiceImpl.java`
|
||||||
|
```java
|
||||||
|
import org.springframework.context.annotation.Lazy;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
@Lazy
|
||||||
|
private CmsArticleService cmsArticleService;
|
||||||
|
```
|
||||||
|
|
||||||
|
**文件4**: `src/main/java/com/gxwebsoft/bszx/controller/BszxBmController.java`
|
||||||
|
```java
|
||||||
|
import org.springframework.context.annotation.Lazy;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
@Lazy
|
||||||
|
private CmsArticleService cmsArticleService;
|
||||||
|
```
|
||||||
|
|
||||||
## 修复详情
|
## 修复详情
|
||||||
|
|
||||||
### 1. CmsNavigationServiceImpl.java 修复
|
### 1. CmsNavigationServiceImpl.java 修复
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import com.gxwebsoft.common.core.annotation.OperationLog;
|
|||||||
import com.gxwebsoft.common.system.entity.User;
|
import com.gxwebsoft.common.system.entity.User;
|
||||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
import io.swagger.v3.oas.annotations.Operation;
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
|
import org.springframework.context.annotation.Lazy;
|
||||||
import org.springframework.security.access.prepost.PreAuthorize;
|
import org.springframework.security.access.prepost.PreAuthorize;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
@@ -34,6 +35,7 @@ public class BszxBmController extends BaseController {
|
|||||||
@Resource
|
@Resource
|
||||||
private BszxBmService bszxBmService;
|
private BszxBmService bszxBmService;
|
||||||
@Resource
|
@Resource
|
||||||
|
@Lazy
|
||||||
private CmsArticleService cmsArticleService;
|
private CmsArticleService cmsArticleService;
|
||||||
|
|
||||||
@PreAuthorize("hasAuthority('bszx:bszxBm:list')")
|
@PreAuthorize("hasAuthority('bszx:bszxBm:list')")
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ import com.gxwebsoft.common.core.utils.ImageUtil;
|
|||||||
import com.gxwebsoft.common.core.web.PageParam;
|
import com.gxwebsoft.common.core.web.PageParam;
|
||||||
import com.gxwebsoft.common.core.web.PageResult;
|
import com.gxwebsoft.common.core.web.PageResult;
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
import org.springframework.context.annotation.Lazy;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.util.CollectionUtils;
|
import org.springframework.util.CollectionUtils;
|
||||||
|
|
||||||
@@ -49,6 +50,7 @@ public class BszxBmServiceImpl extends ServiceImpl<BszxBmMapper, BszxBm> impleme
|
|||||||
@Resource
|
@Resource
|
||||||
private ConfigProperties config;
|
private ConfigProperties config;
|
||||||
@Resource
|
@Resource
|
||||||
|
@Lazy
|
||||||
private CmsArticleService cmsArticleService;
|
private CmsArticleService cmsArticleService;
|
||||||
@Resource
|
@Resource
|
||||||
private BszxClassService bszxClassService;
|
private BszxClassService bszxClassService;
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ import com.gxwebsoft.common.system.entity.User;
|
|||||||
import com.gxwebsoft.common.system.service.UserService;
|
import com.gxwebsoft.common.system.service.UserService;
|
||||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
import io.swagger.v3.oas.annotations.Operation;
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
|
import org.springframework.context.annotation.Lazy;
|
||||||
import org.springframework.security.access.prepost.PreAuthorize;
|
import org.springframework.security.access.prepost.PreAuthorize;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
@@ -52,6 +53,7 @@ public class CmsArticleController extends BaseController {
|
|||||||
@Resource
|
@Resource
|
||||||
private CmsArticleContentService articleContentService;
|
private CmsArticleContentService articleContentService;
|
||||||
@Resource
|
@Resource
|
||||||
|
@Lazy
|
||||||
private CmsNavigationService cmsNavigationService;
|
private CmsNavigationService cmsNavigationService;
|
||||||
@Resource
|
@Resource
|
||||||
private CmsModelService cmsModelService;
|
private CmsModelService cmsModelService;
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ import com.gxwebsoft.common.core.utils.AliYunSender;
|
|||||||
import com.gxwebsoft.common.core.utils.JSONUtil;
|
import com.gxwebsoft.common.core.utils.JSONUtil;
|
||||||
import com.gxwebsoft.common.core.web.PageParam;
|
import com.gxwebsoft.common.core.web.PageParam;
|
||||||
import com.gxwebsoft.common.core.web.PageResult;
|
import com.gxwebsoft.common.core.web.PageResult;
|
||||||
|
import org.springframework.context.annotation.Lazy;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
@@ -33,12 +34,12 @@ import java.util.Map;
|
|||||||
@Service
|
@Service
|
||||||
public class CmsArticleContentServiceImpl extends ServiceImpl<CmsArticleContentMapper, CmsArticleContent> implements CmsArticleContentService {
|
public class CmsArticleContentServiceImpl extends ServiceImpl<CmsArticleContentMapper, CmsArticleContent> implements CmsArticleContentService {
|
||||||
@Resource
|
@Resource
|
||||||
|
@Lazy
|
||||||
private CmsNavigationService cmsNavigationService;
|
private CmsNavigationService cmsNavigationService;
|
||||||
@Resource
|
@Resource
|
||||||
|
@Lazy
|
||||||
private CmsArticleService cmsArticleService;
|
private CmsArticleService cmsArticleService;
|
||||||
@Resource
|
@Resource
|
||||||
private CmsArticleContentService cmsArticleContentService;
|
|
||||||
@Resource
|
|
||||||
private CmsLangLogService cmsLangLogService;
|
private CmsLangLogService cmsLangLogService;
|
||||||
@Override
|
@Override
|
||||||
public PageResult<CmsArticleContent> pageRel(CmsArticleContentParam param) {
|
public PageResult<CmsArticleContent> pageRel(CmsArticleContentParam param) {
|
||||||
@@ -139,7 +140,7 @@ public class CmsArticleContentServiceImpl extends ServiceImpl<CmsArticleContentM
|
|||||||
target.setContent(article.getContent());
|
target.setContent(article.getContent());
|
||||||
System.out.println("target = " + target);
|
System.out.println("target = " + target);
|
||||||
cmsArticleService.updateById(target);
|
cmsArticleService.updateById(target);
|
||||||
cmsArticleContentService.update(new LambdaUpdateWrapper<CmsArticleContent>().eq(CmsArticleContent::getArticleId, target.getArticleId()).set(CmsArticleContent::getContent,target.getContent()));
|
this.update(new LambdaUpdateWrapper<CmsArticleContent>().eq(CmsArticleContent::getArticleId, target.getArticleId()).set(CmsArticleContent::getContent,target.getContent()));
|
||||||
}
|
}
|
||||||
}else {
|
}else {
|
||||||
// 新增操作
|
// 新增操作
|
||||||
@@ -149,7 +150,7 @@ public class CmsArticleContentServiceImpl extends ServiceImpl<CmsArticleContentM
|
|||||||
content.setArticleId(article.getArticleId());
|
content.setArticleId(article.getArticleId());
|
||||||
content.setContent(article.getContent());
|
content.setContent(article.getContent());
|
||||||
content.setTenantId(article.getTenantId());
|
content.setTenantId(article.getTenantId());
|
||||||
cmsArticleContentService.save(content);
|
this.save(content);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ import com.gxwebsoft.common.core.utils.RedisUtil;
|
|||||||
import com.gxwebsoft.common.core.web.PageParam;
|
import com.gxwebsoft.common.core.web.PageParam;
|
||||||
import com.gxwebsoft.common.core.web.PageResult;
|
import com.gxwebsoft.common.core.web.PageResult;
|
||||||
import com.gxwebsoft.common.system.service.UserService;
|
import com.gxwebsoft.common.system.service.UserService;
|
||||||
|
import org.springframework.context.annotation.Lazy;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.util.CollectionUtils;
|
import org.springframework.util.CollectionUtils;
|
||||||
|
|
||||||
@@ -41,12 +42,11 @@ import static com.gxwebsoft.common.core.constants.ArticleConstants.CACHE_KEY_ART
|
|||||||
@Service
|
@Service
|
||||||
public class CmsArticleServiceImpl extends ServiceImpl<CmsArticleMapper, CmsArticle> implements CmsArticleService {
|
public class CmsArticleServiceImpl extends ServiceImpl<CmsArticleMapper, CmsArticle> implements CmsArticleService {
|
||||||
@Resource
|
@Resource
|
||||||
|
@Lazy
|
||||||
private CmsNavigationService cmsNavigationService;
|
private CmsNavigationService cmsNavigationService;
|
||||||
@Resource
|
@Resource
|
||||||
private CmsArticleContentService cmsArticleContentService;
|
private CmsArticleContentService cmsArticleContentService;
|
||||||
@Resource
|
@Resource
|
||||||
private CmsArticleContentService articleContentService;
|
|
||||||
@Resource
|
|
||||||
private UserService userService;
|
private UserService userService;
|
||||||
@Resource
|
@Resource
|
||||||
private CmsModelService cmsModelService;
|
private CmsModelService cmsModelService;
|
||||||
@@ -122,7 +122,7 @@ public class CmsArticleServiceImpl extends ServiceImpl<CmsArticleMapper, CmsArti
|
|||||||
// article.setBanner(model.getBanner());
|
// article.setBanner(model.getBanner());
|
||||||
// }
|
// }
|
||||||
// 附加文字内容
|
// 附加文字内容
|
||||||
CmsArticleContent content = articleContentService.getOne(new LambdaQueryWrapper<CmsArticleContent>().eq(CmsArticleContent::getArticleId, article.getArticleId()).last("limit 1"));
|
CmsArticleContent content = cmsArticleContentService.getOne(new LambdaQueryWrapper<CmsArticleContent>().eq(CmsArticleContent::getArticleId, article.getArticleId()).last("limit 1"));
|
||||||
if (content != null) {
|
if (content != null) {
|
||||||
article.setContent(content.getContent());
|
article.setContent(content.getContent());
|
||||||
}
|
}
|
||||||
@@ -172,9 +172,9 @@ public class CmsArticleServiceImpl extends ServiceImpl<CmsArticleMapper, CmsArti
|
|||||||
content.setArticleId(article.getArticleId());
|
content.setArticleId(article.getArticleId());
|
||||||
content.setContent(article.getContent());
|
content.setContent(article.getContent());
|
||||||
content.setTenantId(article.getTenantId());
|
content.setTenantId(article.getTenantId());
|
||||||
articleContentService.save(content);
|
cmsArticleContentService.save(content);
|
||||||
// 同步翻译并保存
|
// 同步翻译并保存
|
||||||
articleContentService.translate(article);
|
cmsArticleContentService.translate(article);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
@@ -221,11 +221,11 @@ public class CmsArticleServiceImpl extends ServiceImpl<CmsArticleMapper, CmsArti
|
|||||||
String key = CACHE_KEY_ARTICLE + article.getArticleId();
|
String key = CACHE_KEY_ARTICLE + article.getArticleId();
|
||||||
redisUtil.delete(key);
|
redisUtil.delete(key);
|
||||||
// 更新内容
|
// 更新内容
|
||||||
final boolean update = articleContentService.update(new LambdaUpdateWrapper<CmsArticleContent>().eq(CmsArticleContent::getArticleId, article.getArticleId()).set(CmsArticleContent::getContent, article.getContent()));
|
final boolean update = cmsArticleContentService.update(new LambdaUpdateWrapper<CmsArticleContent>().eq(CmsArticleContent::getArticleId, article.getArticleId()).set(CmsArticleContent::getContent, article.getContent()));
|
||||||
if (update) {
|
if (update) {
|
||||||
// 同步翻译并保存
|
// 同步翻译并保存
|
||||||
article.setIsUpdate(true);
|
article.setIsUpdate(true);
|
||||||
articleContentService.translate(article);
|
cmsArticleContentService.translate(article);
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
// 添加内容
|
// 添加内容
|
||||||
@@ -233,7 +233,7 @@ public class CmsArticleServiceImpl extends ServiceImpl<CmsArticleMapper, CmsArti
|
|||||||
content.setArticleId(article.getArticleId());
|
content.setArticleId(article.getArticleId());
|
||||||
content.setContent(article.getContent());
|
content.setContent(article.getContent());
|
||||||
content.setTenantId(article.getTenantId());
|
content.setTenantId(article.getTenantId());
|
||||||
articleContentService.save(content);
|
cmsArticleContentService.save(content);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -43,6 +43,7 @@ public class CmsDesignServiceImpl extends ServiceImpl<CmsDesignMapper, CmsDesign
|
|||||||
@Lazy
|
@Lazy
|
||||||
private CmsNavigationService cmsNavigationService;
|
private CmsNavigationService cmsNavigationService;
|
||||||
@Resource
|
@Resource
|
||||||
|
@Lazy
|
||||||
private CmsArticleContentService cmsArticleContentService;
|
private CmsArticleContentService cmsArticleContentService;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ import com.gxwebsoft.common.core.exception.BusinessException;
|
|||||||
import com.gxwebsoft.common.core.web.PageParam;
|
import com.gxwebsoft.common.core.web.PageParam;
|
||||||
import com.gxwebsoft.common.core.web.PageResult;
|
import com.gxwebsoft.common.core.web.PageResult;
|
||||||
import com.gxwebsoft.common.system.service.UserService;
|
import com.gxwebsoft.common.system.service.UserService;
|
||||||
|
import org.springframework.context.annotation.Lazy;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
@@ -31,6 +32,7 @@ import java.util.List;
|
|||||||
@Service
|
@Service
|
||||||
public class CmsNavigationServiceImpl extends ServiceImpl<CmsNavigationMapper, CmsNavigation> implements CmsNavigationService {
|
public class CmsNavigationServiceImpl extends ServiceImpl<CmsNavigationMapper, CmsNavigation> implements CmsNavigationService {
|
||||||
@Resource
|
@Resource
|
||||||
|
@Lazy
|
||||||
private CmsDesignService cmsDesignService;
|
private CmsDesignService cmsDesignService;
|
||||||
@Resource
|
@Resource
|
||||||
private CmsModelService cmsModelService;
|
private CmsModelService cmsModelService;
|
||||||
|
|||||||
Reference in New Issue
Block a user