錯誤資訊:java.lang.StackOverflowError
關于這個錯誤的深度解析,大家可以參考這篇博文,比較詳細:https://blog.csdn.net/zc375039901/article/details/79179465\
先說說這個錯誤,我是怎麼發生的?我的這個錯誤與上面我推薦的該錯誤原因深度解析沒有多大的關系,大家可以适當了解了解。
簡單的說,這是一個低級錯誤,特别對于"碼農"頭銜的大多數開發者而言。
習慣了慣性思維,習慣的複制粘貼,習慣了那套編寫業務邏輯層的方式。
貼代碼講示例:
錯誤代碼:
@Service
public class SysModuleServiceImpl extends ServiceImpl<SysModuleDao, SysModule> implements SysModuleService {
@Autowired
private SysModuleService sysModuleService;
@Override
public List<SysModule> queryModuleListInfo(Map<String, Object> map) {
// TODO Auto-generated method stub
return sysModuleService.queryModuleListInfo(map);
}
@Override
public int queryModuleCountInfo(Map<String, Object> map) {
// TODO Auto-generated method stub
return sysModuleService.queryModuleCountInfo(map);
}
}
這是我一時疏忽,這樣寫了,其實也不能說是一時疏忽,隻能說是思維定勢導緻的。
開發者們一定不能思維定勢,對于思維定勢的開發者們,業界有這樣一句名言,做五年的開發,相當于一年而已或者是開發多年,還是在那一套章法上循環往複。
不多說大道理了,關于上面的代碼為什麼不能這麼寫,為什麼是錯的,下面我将進行解答。
首先來說,@Service這個注解,大家應該不陌生了,特别是對于Java開發者們。
與這個注解并列的有@Reponsitory,@Component,@Controller,這些對于奮戰一線的開發者們,早已眼熟而詳了。
關于上面我為什麼會犯這個錯誤?因為我忽略了依賴注入。
通常情況下,業務邏輯層直接與資料通路層互動,而Dao層,早已認證MyBatis動态掃描,注入了也就是在對應的spring-mybatis.xml檔案配置了Bean。
當然了,這裡要提一點,之是以不用MyBatis非動态掃描的方式,最大的原因是難以維護,不友善管理,因為如果采用這種方式,每個對應的Dao,我都要專門寫一個bean進行管理,這樣非常不好。特别對于業務需求時常變化,甚至以後功能擴充,代碼重構都會帶來很大的麻煩。而采用動态掃描的方式,則隻要在Spring-MyBatis.xml配置對應的如下所示即可,這裡我用的是MyBatis Plus,MyBatis Plus和MyBatis同Spring整合,基本上是沒有差別的,除了一些特殊的插件和其他優化配置之外。
<!-- Spring整合Mybatis,更多檢視文檔:http://mp.baomidou.com -->
<bean id="sqlSessionFactory" class="com.baomidou.mybatisplus.spring.MybatisSqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<!-- 自動掃描Mapping.xml檔案 -->
<property name="mapperLocations" value="classpath:mybatis/system/*.xml"/>
<property name="configLocation" value="classpath:mybatis/mybatis-config.xml"/>
<property name="typeAliasesPackage" value="com.blog.entity"/>
<property name="plugins">
<array>
<!-- 分頁插件配置 -->
<bean id="paginationInterceptor" class="com.baomidou.mybatisplus.plugins.PaginationInterceptor">
</bean>
</array>
</property>
<!-- 全局配置注入 -->
<property name="globalConfig" ref="globalConfig" />
</bean>
<bean id="globalConfig" class="com.baomidou.mybatisplus.entity.GlobalConfiguration">
<!--
AUTO->`0`("資料庫ID自增")
INPUT->`1`(使用者輸入ID")
ID_WORKER->`2`("全局唯一ID")
UUID->`3`("全局唯一ID")
-->
<property name="idType" value="2" />
</bean>
<!-- MyBatis 動态掃描 -->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.blog.daor"/>
</bean>
關鍵一行就是動态掃描這一行,還有就是對應的xml配置檔案,上面和下面結合使Dao接口與xml檔案中的sql進行綁定。
業務邏輯層是基于資料通路層的,如果直接業務邏輯層按照我文章開頭那樣的錯誤代碼寫法,是無法通路Dao層的。
另外大家要知道一點,層與層之間是雙向關系,資料通路層依賴于資料庫,資料庫如果有什麼異常,是會報錯的,業務邏輯層依賴于資料通路層,控制層也就是接口層或者路由層,因為這裡主要是處理前台請求的,并根據對應的邏輯傳回對應的資料或者某種提示資訊等等。
正确代碼如下:
@Service
public class SysModuleServiceImpl extends ServiceImpl<SysModuleDao, SysModule> implements SysModuleService {
@Autowired
private SysModuleDao sysModuleDao;
@Override
public List<SysModule> queryModuleListInfo(Map<String, Object> map) {
// TODO Auto-generated method stub
return sysModuleDao.queryModuleListInfo(map);
}
@Override
public int queryModuleCountInfo(Map<String, Object> map) {
// TODO Auto-generated method stub
return sysModuleDao.queryModuleCountInfo(map);
}
}
這裡還要提一下,為什麼要有業務邏輯層,簡單的說,業務邏輯層主要是為了複用資料通路層,實際業務是非常複雜的,需要整合多個資料通路層來達到實作業務的目的,比如拿智能門鎖來說,我需要知道門鎖編碼是否存在,之前是否批量導入,根據我們的業務,與我們合作商,購買我們的門鎖,通常購買一般以批次來衡量,比如他們購買了我們100把門鎖,我們在背景通過一個Excel資料記錄對應的門鎖編号和其他相關資料,将其錄入到我們的資料表中(批量導入),然後對方使用我們的背景管理系統進行安裝,雖然我們導入了但是尚未激活,門鎖有一個對應的狀态,預設為0(尚未安裝的或尚未激活的意思)。
當他們安裝時,首先需要判斷安裝門鎖編碼是否存在,另外他們用于住宿方面,酒店編号和房間編号是否存在(這裡使用我們對應的智能酒店管理系統與智能門鎖背景系統進行關聯,還有就是網關,判斷網關是否安裝,而且網關涉及到我們另外的資料表,為了使門鎖與網關結合,我們需要編寫一個方法,該方法涉及兩張表的業務方面,是以這裡就需要業務邏輯層,這裡我想表達的意思是,業務邏輯層就是為了更好的處理業務和複用業務,以此來達到建構一個可擴充性好,可維護性好,穩定性好的web系統。
小結:這裡我想告訴大家的是,不要忽視任何一個錯誤以及對于程式設計人員而言,是用腦來思考程式設計如何做的更好,而不是慢慢的變為一個重複性的體力勞動。當然了,部落客我目前也沒有完全做到,是以需要不斷的學習和實際中不斷的反思總結,以此來達到做最優秀的程式員和寫一手優雅的代碼目的。