類之間的循環依賴指的的A依賴B,B也依賴A,這就出現循環依賴。如果是spring容器中的兩個bean出現循環依賴,則在容器啓動時,可能會報錯,導致無法啓動。
如果解決循環依賴?
首先要理清各類的職責,尤其是分層職責————相同層級不要相互調用,調用下級API。
下面是職責不清晰導致的循環依賴。解決方案是,調用下層方法。UserService和LoginAccountService是同一層服務,那麼,他們在調用對方的數據時,應調用其下層的方法。例如:UserService#selectUserInfo在獲取LoginAccount數據時,改爲調用loginAccountMapper#selectByUserId。這樣就解決了bean直接的循環依賴。
// ------------------------- UserService ------------------------------------ @Service public class UserService { @Resource private UserMapper userMapper; @Resource private LoginAccountService loginAccountService; public UserVO selectUserInfo(int userId) { User user = userMapper.selectByUserId(userId); if (user == null) { throw new ResponseException("用戶不存在"); } UserVO userVO = BeanMapper.map(user, UserVO.class); LoginAccount loginAccount= loginAccountService.selectByUserId(userId); if (loginAccount!=null){ userVO.setLoginAccount(loginAccount.getLoginAccount()); } return userVO; } public void validUser(int userId) { User user = userMapper.selectByUserId(userId); if (user == null) { throw new ResponseException("用戶不存在"); } if (!"NORMAL".equalsIgnoreCase(user.getStatus())) { throw new ResponseException("用戶已禁用"); } } } // --------------------------- LoginAccountService ---------------------------------- @Service public class LoginAccountService { @Resource private UserService userService; @Resource private LoginAccountMapper loginAccountMapper; public LoginAccount login(String loginAccount, String password) { // 獲取登陸賬號 LoginAccount entity = loginAccountMapper.selectByAccount(loginAccount); if (entity == null) { throw new ResponseException("賬號不存在"); } if (!password.equals(entity.getPassword())) { throw new ResponseException("用戶密碼錯誤"); } userService.validUser(entity.getUserId()); return entity; } public LoginAccount selectByUserId(int userId) { return loginAccountMapper.selectByUserId(userId); } }
當然,上面的循環依賴,單從技術層面,加@Lasy是可以解決的,但還是應該從類的職責方面來進行改進。職責不清晰會帶來諸多問題,絕不僅僅是重複依賴的問題。
還有一種情況,也是我今天碰到的一個情況。跟大家分享一下。
我們的中臺channel服務,對接了數家銀行通道。其中的一個YiLian通道有個特殊需求,在支付時需要對收款人進行報備,報備完成纔可下發。見下圖示意圖,YiLianPayStrategy 有注入PayUserSignService,PayUserSignService有注入YiLianSignStrategy,YiLianSignStrategy有注入YiLianPayStrategy。 這就導致了YiLianPayStrategy 與YiLianSignStrategy的相互循環依賴。
這在企業應用開發中是個比較典型的正常案例。那麼,如果解決這種循環依賴呢?
解決方案有二:
1. 不使用bean注入的方式,改爲需要時才獲取bean。
2. 使用spring的事件監聽器,實現類之間的解耦。
感謝閱讀!正在編寫,尚未完成。