<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
最近做專案,有個需求是和外部對接,從介面獲取新聞資料,把資料和快取中的資料對比,多了的新增到資料庫,少了的刪掉。
介面有兩個,一開始我是在業務類裡寫了兩個方法,程式碼太長,簡單說就是兩個部分:
public Object saveANews() { //1、獲取A介面新聞列表 //2、和快取對比,存資料到資料庫 } public Object saveBNews() { //1、獲取B新聞列表 //2、和快取對比,存資料到資料庫 }
寫完後我發現,因為操作的是資料庫的同一張表,2的部分程式碼完全一模一樣,只有1的部分不同,而1的部分其實就只有一行程式碼。。。
這必須得複用啊,而且是一個業務,也沒必要分別用兩個方法,於是我改成了這樣:
//業務介面實現方法 public Object saveNews(NewsUtilService service) { //1、獲取介面新聞列表 List<NewsVO> list = service.queryNews(); //2、和快取對比,存資料到資料庫 } //定義新聞資料介面 public interface NewsUtilService { List<NewsVO> queryNews(); } //介面的兩個實現類 @Service public class ANewsDataServiceImpl implements NewsUtilService { @Autowired private NewsDataMapper newsDataMapper; @Override public List<NewsVO> queryNews(){ //對接資料 } } @Service public class BNewsDataServiceImpl implements NewsUtilService { @Override public List<NewsVO> queryNews(){ //對接資料 } } //定義工廠類 @Service public class NewsUtilServiceFactory { /** * * Method Name: getNewsUtilService * @param source * @return */ public NewsUtilService getNewsUtilService(String source){ switch(source){ case "a": return new ANewsDataServiceImpl(); case "b": return new BNewsDataServiceImpl(); default: return null; } } } //控制層呼叫 @RestController public class NewsDataController { @Resource private NewsDataService newsDataService; @Resource private NewsUtilServiceFactory factory; public Object getNewsData(){ String[] sources = {"a","b"}; for (int i = 0; i < sources.length; i++) { NewsUtilService newsUtilService = factory.getNewsUtilService(sources[i]); newsDataService.saveNews(newsUtilService); } } }
本來以為這就大工告成了,誰知道執行後控制檯居然報錯了:
經過一步步偵錯,總算髮現了是什麼問題:
其中一個實現類中注入的Mapper沒有範例化,是null。
一開始我還以為是建構函式呼叫和注入的順序問題,查了半天才明白不是,問題在這裡:
使用new關鍵字範例化的物件不是被spring建立的,不歸spring管,所以A類實現類中Mapper注入的註解根本不生效!
但是因為業務需要,那個mapper又需要用到,怎麼辦呢?
1、在介面的方法引數里加入mapper,把mapper作為引數傳進去,但這實在太奇怪了,先不說B類實現類根本用不到mapper,而且一個介面定義出來後根本不管它的實現類吧,因為實現類的問題去改介面,,,似乎有點非呀。
於是決定用第二種,修改工廠類變成如下:
//定義工廠類 @Service public class NewsUtilServiceFactory { @Autowired private ANewsDataServiceImpl aNewsDataServiceImpl; @Autowired private BNewsDataServiceImpl bNewsDataServiceImpl; public NewsUtilService getNewsUtilService(String source){ switch(source){ case "a": return aNewsDataServiceImpl; case "b": return bNewsDataServiceImpl; default: return null; } } }
程式碼寫出來自己都無語了,先把所有的實現類都範例化出來,在根據輸入返回。這不是工廠模式,是商店模式吧。。。但是當時也想不到其他辦法,就先這麼寫了,但一直覺得肯定有其他解決方案,直到今天有空,去查了一下,才發現自己都多low。。。
其實spring可以動態獲取實現類的~~~
@Service public class NewsUtilServiceFactory { @Autowired private ApplicationContext applicationContext; public NewsUtilService getNewsUtilService(String source){ switch(source){ case "web": return applicationContext.getBean(WebNewsDataServiceImpl.class); case "oa": return applicationContext.getBean(OANewDataServiceImpl.class); default: return null; } } }
這才是正確寫法有木有!
總算弄出來了,趕緊記錄下來先~
在springboot專案中,為了方便,我們可能需要獲取某一個介面下面的所有實現類,根據名稱進行匹配使用。
1、ServiceLocator.java
package com.yang.config; import com.yang.workOrder.service.IRootService; import org.springframework.beans.BeansException; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import org.springframework.stereotype.Component; import java.util.Map; /** * explain:獲取應用上下文並獲取相應的介面實現類 * * @author yang * @date 2021/1/5 */ @Component public class ServiceLocator implements ApplicationContextAware { /** * 用於儲存介面實現類名及對應的類 */ private Map<String, IRootService> map; /** * 獲取應用上下文並獲取相應的介面實現類 * @param applicationContext * @throws BeansException */ @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { //根據介面型別返回相應的所有bean map = applicationContext.getBeansOfType(IRootService.class); } /** * 獲取所有實現集合 * @return */ public Map<String, IRootService> getMap() { return map; } /** * 獲取對應服務 * @param key * @return */ public IRootService getService(String key) { return map.get(key); } }
2、IRootService.java
package com.yang.workOrder.service; import com.alibaba.fastjson.JSONObject; import com.yang.workOrder.entity.WorkOrder; /** * explain:基礎流程操作服務介面 * * @author yang * @date 2021/1/5 */ public interface IRootService { /** * 開始流程 * @param workOrder * @return */ boolean startProcess(WorkOrder workOrder); }
3、RootA001ServiceImpl.java
package com.yang.workOrder.service.impl; import com.alibaba.fastjson.JSONObject; import com.yang.workOrder.entity.WorkOrder; import com.yang.workOrder.service.IRootService; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Service; /** * explain:A_001流程審批實現類 * * @author yang * @date 2021/1/5 */ @Service("A_001") public class RootA001ServiceImpl implements IRootService { private static final Logger LOGGER = LoggerFactory.getLogger(RootA001ServiceImpl.class); @Override public boolean startProcess(WorkOrder workOrder) { return false; } }
4、RootA002ServiceImpl.java
package com.yang.workOrder.service.impl; import com.alibaba.fastjson.JSONObject; import com.yang.workOrder.entity.WorkOrder; import com.yang.workOrder.service.IRootService; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Service; /** * explain:A_002流程審批實現類 * * @author yang * @date 2021/1/5 */ @Service("A_002") public class RootA002ServiceImpl implements IRootService { private static final Logger LOGGER = LoggerFactory.getLogger(RootA002ServiceImpl.class); @Override public boolean startProcess(WorkOrder workOrder) { return false; } }
以上為個人經驗,希望能給大家一個參考,也希望大家多多支援it145.com。
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45