自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

選定對(duì)象批量織入“x.set(y.get)”代碼,自動(dòng)生成vo2dto

開(kāi)發(fā) 前端
這些年從事編程開(kāi)發(fā)以來(lái),我好像發(fā)現(xiàn)了大部分研發(fā)那些不愿意干的事,都成就了別人。就像部署服務(wù)麻煩,有了Docker、簡(jiǎn)單CRUD不想開(kāi)發(fā),有了低代碼、給方法代碼加監(jiān)控繁瑣、有了非入侵的全鏈路監(jiān)控。

[[440440]]

本文轉(zhuǎn)載自微信公眾號(hào)「bugstack蟲(chóng)洞?!?,作者小傅哥。轉(zhuǎn)載本文請(qǐng)聯(lián)系bugstack蟲(chóng)洞棧公眾號(hào)。

一、前言

給你機(jī)會(huì),你也不中用啊

這些年從事編程開(kāi)發(fā)以來(lái),我好像發(fā)現(xiàn)了大部分研發(fā)那些不愿意干的事,都成就了別人。就像部署服務(wù)麻煩,有了Docker、簡(jiǎn)單CRUD不想開(kāi)發(fā),有了低代碼、給方法代碼加監(jiān)控繁瑣、有了非入侵的全鏈路監(jiān)控。

而這些原本你也在干的事情,因?yàn)闆](méi)有想法、沒(méi)有創(chuàng)新、沒(méi)有思考,也可能是沒(méi)有能力,所以一直都是在搬磚、碼磚、砌磚,反反復(fù)復(fù)、來(lái)來(lái)回回。鍵盤(pán)敲的是越來(lái)越快了,代碼搞的是越來(lái)越爛了。薪資沒(méi)搞上去,頭發(fā)是越來(lái)越少了。

對(duì)于想走技術(shù)路線的碼農(nóng),千萬(wàn)不要只是停留在業(yè)務(wù)功能的邏輯開(kāi)發(fā)上,只有當(dāng)你有了共性凝練的邏輯思維,才會(huì)逐步思考怎么把一件重復(fù)的事做成一個(gè)通用的服務(wù)或者組件,而這些東西的落地不僅需要你會(huì)寫(xiě)代碼,還要會(huì)思考更要會(huì)去索引一些你需要的技術(shù),并用自學(xué)的方式來(lái)補(bǔ)充這部分技能。

二、需求目的

你想寫(xiě)對(duì)象間的get、set嗎?煩,煩死了,尤其是在DDD四層架構(gòu)下,有了多層防污處理,一會(huì)一個(gè)vo2dto、一會(huì)一個(gè)vo2do、一會(huì)一個(gè)do2po,雖然有很多工具的操作,但還是得寫(xiě)呀。

怎么辦?不要慌,這是機(jī)會(huì)呀,我們做個(gè)插件搞定它,讓它可以自動(dòng)的給我生成get、set代碼,在IDEA Plugin的處理下,選擇好需要生成對(duì)象代碼的錨點(diǎn),復(fù)制下轉(zhuǎn)換對(duì)象,自動(dòng)織入代碼,1s鐘搞定!效果視頻

三、案例開(kāi)發(fā)

1. 工程結(jié)構(gòu)

  1. guide-idea-plugin-vo2dto 
  2. ├── .gradle 
  3. └── src 
  4.     ├── main 
  5.     │   └── java 
  6.     │    └── cn.bugstack.guide.idea.plugin  
  7.     │        ├── action 
  8.     │        │   └── Vo2DtoGenerateAction.java      
  9.     │        ├── application 
  10.     │        │   └── IGenerateVo2Dto.java       
  11.     │        ├── domain 
  12.     │        │   ├── model 
  13.     │        │   │   ├── GenerateContext.java      
  14.     │        │   │   ├── GetObjConfigDO.java       
  15.     │        │   │   └── SetObjConfigDO.java        
  16.     │        │   └── service    
  17.     │        │       ├── impl      
  18.     │        │       │   └── GenerateVo2DtoImpl.java     
  19.     │        │       └── AbstractGenerateVo2Dto.java       
  20.     │        └── infrastructure    
  21.     │            └── Utils.java     
  22.     ├── resources 
  23.     │   └── META-INF 
  24.     │       └── plugin.xml  
  25.     ├── build.gradle   
  26.     └── gradle.properties 

在此 IDEA 插件工程中,主要分為4塊區(qū)域:

action:提供菜單欄窗體,在插件中我們把這個(gè)菜單欄配置到 Generate 下,也就是通常你生成 get、set、constructor 方法的地方。

application:應(yīng)用層定義接口,這里定義了一個(gè)用于生成代碼并織入到錨點(diǎn)的方法接口。

domian:領(lǐng)域?qū)訉iT(mén)處理代碼的生成和織入動(dòng)作,這一層把代碼的中錨點(diǎn)位置獲取、剪切板信息復(fù)制、應(yīng)用上下文、類(lèi)中g(shù)et、set的解析,以及最終把生成代碼織入到錨點(diǎn)后的操作。

infrastructure:在基礎(chǔ)層提供了工具類(lèi),用于獲取剪切板信息和錨點(diǎn)位置判斷等操作。

2. 織入代碼接口

cn.bugstack.guide.idea.plugin.application.IGenerateVo2Dto

  1. public interface IGenerateVo2Dto { 
  2.  
  3.     void doGenerate(Project project, DataContext dataContext); 
  4.  

定義接口其實(shí)非常重要的一步,因?yàn)檫@樣一步就把生成的標(biāo)準(zhǔn)定義下來(lái)了,所有的生成動(dòng)作都要從這個(gè)接口發(fā)起。學(xué)習(xí)源碼也一樣,你要找到一個(gè)核心的入口點(diǎn),才能更好的開(kāi)始學(xué)習(xí)

3. 定義模板方法

因?yàn)樯纱a并織入錨點(diǎn)位置的操作,整個(gè)來(lái)看其實(shí)也是一套流程操作,因?yàn)樵谶@個(gè)過(guò)程需要;獲取上下文信息(也就是工程對(duì)象)、給當(dāng)前錨點(diǎn)位置的類(lèi)提取 set 方法集合、之后在給Ctrl+C剪切板上的信息讀取出來(lái)提取 get 方法集合,第四步把set、get進(jìn)行組合并織入代碼到錨點(diǎn)位置。整體過(guò)程如下:

那么在使用模板方法后,就可以非常容易的把寫(xiě)在一個(gè)類(lèi)里的成片的代碼按照職責(zé)進(jìn)行拆分。

同時(shí)因?yàn)橛辛四0宓亩x,也就定義出了整個(gè)一套標(biāo)準(zhǔn)流程,在流程規(guī)范下執(zhí)行代碼,后續(xù)再補(bǔ)充邏輯迭代功能也會(huì)更加容易。

4. 代碼織入錨點(diǎn)

關(guān)于代碼織入錨點(diǎn)前,我們?cè)谀0孱?lèi)中定義的方法,需要實(shí)現(xiàn)接口進(jìn)行處理,重點(diǎn)包括:

  • 通過(guò) CommonDataKeys.EDITOR.getData(dataContext)、CommonDataKeys.PSI_ELEMENT.getData(dataContext) 封裝 GenerateContext 對(duì)象上下文信息,也就是一些類(lèi)、錨點(diǎn)位置、文檔編輯的對(duì)象。
  • 通過(guò) PsiClass 獲取光標(biāo)位置對(duì)應(yīng)的 Class 類(lèi)信息,在通過(guò) psiClass.getMethods() 讀取對(duì)象方法,把 set 方法過(guò)濾出來(lái),封裝到集合中。
  • 通過(guò) Toolkit.getDefaultToolkit().getSystemClipboard() 獲取剪切板信息,也就是你在錨點(diǎn)位置給對(duì)象生成 x.set(y.get) 時(shí),復(fù)制的 Y y 對(duì)象,并開(kāi)始提取 get 方法,同樣封裝到集合中。
  • 那么最后就是代碼的組裝和織入動(dòng)作了,這部分我們的代碼如下;

cn.bugstack.guide.idea.plugin.domain.service.impl.GenerateVo2DtoImpl

  1. @Override 
  2. protected void weavingSetGetCode(GenerateContext generateContext, SetObjConfigDO setObjConfigDO, GetObjConfigDO getObjConfigDO) { 
  3.     Application application = ApplicationManager.getApplication(); 
  4.     // 獲取空格位置長(zhǎng)度 
  5.     int distance = Utils.getWordStartOffset(generateContext.getEditorText(), generateContext.getOffset()) - generateContext.getStartOffset(); 
  6.     application.runWriteAction(() -> { 
  7.         StringBuilder blankSpace = new StringBuilder(); 
  8.         for (int i = 0; i < distance; i++) { 
  9.             blankSpace.append(" "); 
  10.         } 
  11.         int lineNumberCurrent = generateContext.getDocument().getLineNumber(generateContext.getOffset()) + 1; 
  12.         List<String> setMtdList = setObjConfigDO.getParamList(); 
  13.         for (String param : setMtdList) { 
  14.             int lineStartOffset = generateContext.getDocument().getLineStartOffset(lineNumberCurrent++); 
  15.             new WriteCommandAction(generateContext.getProject()) { 
  16.                 @Override 
  17.                 protected void run(@NotNull Result result) throws Throwable { 
  18.                     generateContext.getDocument().insertString(lineStartOffset, blankSpace + setObjConfigDO.getClazzParamName() + "." + setObjConfigDO.getParamMtdMap().get(param) + "(" + (null == getObjConfigDO.getParamMtdMap().get(param) ? "" : getObjConfigDO.getClazzParam() + "." + getObjConfigDO.getParamMtdMap().get(param) + "()") + ");\n"); 
  19.                     generateContext.getEditor().getCaretModel().moveToOffset(lineStartOffset + 2); 
  20.                     generateContext.getEditor().getScrollingModel().scrollToCaret(ScrollType.MAKE_VISIBLE); 
  21.                 } 
  22.             }.execute(); 
  23.         } 
  24.     }); 
  • 織入代碼的流程動(dòng)作,主要是對(duì)set方法集合進(jìn)行遍歷,把對(duì)應(yīng)的x.set(y.get)通過(guò) document.insertString 到具體的位置和代碼。
  • 最終所有生成的代碼方法織入完成,即完成了整個(gè) x.set(y.get) 的過(guò)程。

5. 配置菜單入口

plugin.xml

  1. <actions> 
  2.     <!-- Add your actions here --> 
  3.     <action id="Vo2DtoGenerateAction" class="cn.bugstack.guide.idea.plugin.action.Vo2DtoGenerateAction" 
  4.             text="Vo2Dto - 小傅哥" description="Vo2Dto generate util" icon="/icons/logo.png"
  5.         <add-to-group group-id="GenerateGroup" anchor="last"/> 
  6.         <keyboard-shortcut keymap="$default" first-keystroke="ctrl shift K"/> 
  7.     </action
  8. </actions> 

 

 

這次我們給生成 x.set(y.get) 代碼的操作加個(gè)快捷鍵,可以讓我們更加方便的進(jìn)行操作。

四、測(cè)試驗(yàn)證

點(diǎn)擊 Plugin 啟動(dòng) IDEA 插件,之后有2步操作;

  • 復(fù)制你需要被轉(zhuǎn)換的對(duì)象,因?yàn)閺?fù)制以后就可以被插件獲取到剪切板信息了,也就能提取到get方法集合。
  • 把鼠標(biāo)定義到需要轉(zhuǎn)換設(shè)置值的對(duì)象,之后鼠標(biāo)右鍵,選擇 Generate -> Vo2Dto - 小傅哥

1. 復(fù)制對(duì)象

2. 生成對(duì)象

3. 最終效果

最終你就可以看到已經(jīng)把你全部的對(duì)象轉(zhuǎn)換,自動(dòng)生成出來(lái)代碼了,是不是很香。

如果你直接使用快捷鍵 Ctrl + Shift + K 也是可以自動(dòng)生成的。

五、擴(kuò)展接口

   
獲取當(dāng)前編輯的文件, 通過(guò)PsiFile可獲得PsiClass, PsiField等 PsiFile psiFile = e.getData(LangDataKeys.PSI_FILE);
獲取當(dāng)前的project對(duì)象 Project project = e.getProject();
獲取數(shù)據(jù)上下文 DataContext dataContext = e.getDataContext();
獲取到數(shù)據(jù)上下文后,通過(guò)CommonDataKeys對(duì)象可以獲得該File的所有信息 Editor editor = CommonDataKeys.EDITOR.getData(dataContext);<br />PsiFile psiFile = CommonDataKeys.PSI_FILE.getData(dataContext);<br />VirtualFile virtualFile = CommonDataKeys.VIRTUAL_FILE.getData(dataContext);
GlobalSearchScope中有Project域,Moudule域,F(xiàn)ile域等等 PsiFile[] psiFiles = FilenameIndex.getFilesByName(project, name, GlobalSearchScope);
類(lèi)似于IDE中的Find Usages操作 Query<PsiReference> search = ReferencesSearch.search(PsiElement);
重命名 RenameRefactoring newName = RefactoringFactory.getInstance(Project).createRename(PsiElement, "newName");
搜索一個(gè)類(lèi)的所有子類(lèi),重載方法較多,具體不再一一列出 Query<PsiClass> search = ClassInheritorsSearch.search(PsiClass);
根據(jù)類(lèi)的全限定名查詢PsiClass,下面這個(gè)方法是查詢Project域 PsiClass psiClass = JavaPsiFacade.getInstance(project).findClass(classQualifiedName, GlobalSearchScope.projectScope(project));
獲取Java類(lèi)所在的Package PsiPackage psiPackage = JavaPsiFacade.getInstance(Project).findPackage(classQualifiedName);
查找被特定方法重寫(xiě)的方法 Query<PsiMethod> search = OverridingMethodsSearch.search(PsiMethod);

六、總結(jié)

本章節(jié)中我們涉及了不少對(duì)工程對(duì)象的類(lèi)和方法進(jìn)行操作的處理,這些內(nèi)容的實(shí)踐也非常適合你在其他場(chǎng)景使用,比如給工程的接口生成一些自動(dòng)化API的操作。

在給對(duì)象生成 x.set(y.get) 的時(shí)候,我也在思考該怎么更合理的把轉(zhuǎn)換對(duì)象代入到插件的代碼邏輯中,可能會(huì)想到是通過(guò)彈窗配置或者代碼掃描到上一行,但這樣的方式終究是不舒服的,考慮到實(shí)際自己編碼的習(xí)慣操作,其實(shí)我們做這步的時(shí)候,復(fù)制是第一步動(dòng)作,為了更好的體驗(yàn),所以這里選擇了用復(fù)制來(lái)處理這塊的連接性問(wèn)題。

本系列的 IDEA Plugin 開(kāi)發(fā)都以遵循 DDD 工程結(jié)構(gòu)思想為設(shè)計(jì)和實(shí)現(xiàn),雖然整體內(nèi)容看上去也不復(fù)雜,但希望這些框架的沉淀可以為 DDD 落地鋪路,讓更多的工程研發(fā)人員適應(yīng) DDD 結(jié)構(gòu)。

 

責(zé)任編輯:武曉燕 來(lái)源: bugstack蟲(chóng)洞棧
相關(guān)推薦

2022-12-09 07:53:20

vo2dto方法AOP

2021-10-12 10:49:52

Vo2dto壓測(cè)數(shù)據(jù)

2024-11-29 07:34:36

PO持久化對(duì)象

2022-09-13 08:40:51

DTOVOPO

2021-03-08 08:54:12

驅(qū)動(dòng)模型DTODO

2024-10-16 17:01:17

Java開(kāi)發(fā)SpringBoot

2009-07-16 09:09:36

ibatis自動(dòng)代碼

2009-09-11 09:15:32

C# get set

2012-04-19 17:16:32

Titanium實(shí)例代碼分析

2009-09-10 16:38:43

C# get set用

2014-01-21 09:42:32

Python代碼對(duì)象

2023-06-12 00:38:55

開(kāi)源Java庫(kù)工具

2025-02-05 11:00:00

開(kāi)發(fā)Java對(duì)象模型

2010-09-28 13:50:20

2009-09-10 15:27:16

C# get set

2010-09-25 16:06:58

SQL語(yǔ)句

2009-08-27 15:22:27

C#中的GET與SET

2023-11-09 09:28:09

Java代碼

2022-12-22 08:57:29

Redis數(shù)據(jù)存儲(chǔ)

2009-07-14 17:12:26

ibatis自動(dòng)代碼生
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)