,转载请联系bugstack公众号。1.前言给了你机会,你却没用!从事编程和开发这些年,我似乎发现,在研发中,大部分不想做的事,都成就了别人。就像部署服务的麻烦一样,用Docker,简单的CRUD不想开发,代码少,方法代码加监控麻烦,无侵入的全链路监控。而这些事情你也在做,因为你没有想法,没有创新,没有思考,也许还没有能力,所以你一直在搬砖,堆砖,砌砖,周而复始,来来回回。键盘打字越来越快,代码越来越烂。工资一直没有提高,头发也越来越少。对于想走技术路线的码农,不要只停留在业务功能的逻辑开发上。只有当你有了通用简洁的逻辑思维,你才会逐渐思考如何把一个重复的东西做成一个通用的服务或者组件,而这些东西的实现不仅需要你会写代码,还需要能够思考和索引一些你需要的技术,并通过自学来补充这部分技能。2.需求目的对象之间要写get和set吗?烦,烦,尤其是DDD四层架构下,加上多层抗污染处理,一层vo2dto,一层vo2do,一层Ado2po,虽然有很多工具可以操作,还是得写。我应该怎么办?不要惊慌,这是一个机会。我们做一个插件来修复它,让它自动为我生成get和set代码。在IDEAPlugin的处理下,选择需要生成目标代码的锚点,将其复制Convertobjects,自动编织成代码,1秒搞定!效果视频:3.案例开发1.项目结构guide-idea-plugin-vo2dto├──.gradle└──src├──main│└──java│└──cn.bugstack.guide.idea.plugin│├──action│└──Vo2DtoGenerateAction.java│├──application││└──IGenerateVo2Dto.java│├──domain│├──model││...─AbstractGenerateVo2Dto.java│└──基础设施│└──Utils.java├──resources│└──META-INF│└──plugin.xml├──build.gradle└──gradle.properties在这个IDEA插件项目中,主要分为4个areas:Action:提供一个菜单栏表单。在插件中,我们把这个菜单栏配置在Generate下,这里就是你平时生成get、set、constructor方法的地方。application:应用层定义接口,定义了生成代码并织入锚点的方法接口。domian:领域层专门负责代码生成和编织动作。该层获取代码中的锚点位置,复制剪贴板信息,应用上下文,解析类中的get和set,最后将生成的代码编织成到达锚点后的操作。infrastructure:提供底层的工具类,用于获取剪贴板信息、锚点位置判断等操作。2.织入代码界面cn.bugstack.guide.idea.plugin.application.IGenerateVo2DtopublicinterfaceIGenerateVo2Dto{voiddoGenerate(Projectproject,DataContextdataContext);}其实是定义界面非常重要的一步,因为这一步定义了生成的标准,所有必须从此界面启动生成操作。学习源代码也是如此。您需要找到一个核心切入点才能更好地开始学习。3.定义模板方法因为生成代码并织入锚点位置的操作实际上是一个整体的一组流程操作,因为在这个流程中需要;获取context信息(即project对象),提取当前锚点位置的类的set方法集,然后读取ctrl+C剪贴板上的信息提取get方法集,第四步是toset,get组合并将代码编织到锚点位置。整体流程如下:使用模板方法后,很容易将写在一个类中的代码块按照职责进行拆分。同时,因为模板的定义,定义了一整套标准的流程,在流程规范下执行代码会更容易,后期添加逻辑迭代功能。4.代码织入锚点在代码织入锚点之前,我们在模板类中定义的方法需要实现接口进行处理。关键点包括:通过CommonDataKeys.EDITOR.getData(dataContext),CommonDataKeys.PSI_ELEMENT.getData(dataContext)封装了GenerateContext对象的上下文信息,即一些类的对象,锚点位置,文档编辑等。通过PsiClass获取光标所在位置对应的Class信息,通过psiClass.getMethods()读取对象方法,过滤掉set方法,封装成集合。通过Toolkit.getDefaultToolkit().getSystemClipboard()获取剪贴板信息,即当你为锚点处的对象生成x.set(y.get)时,复制Yy对象,开始提取get方法,它也被封装到集合中。那么最后就是代码的组装和编织了。这部分我们的代码如下;getApplication();//获取空格位置长度intdistance=Utils.getWordStartOffset(generateContext.getEditorText(),generateContext.getOffset())-generateContext.getStartOffset();application.runWriteAction(()->{StringBuilderblankSpace=newStringBuilder();for(inti=0;i
虚拟文件virtualFile=CommonDataKeys.VIRTUAL_FILE.getData(dataContext);GlobalSearchScope有Project域、Moudule域、File域等PsiFile[]psiFiles=FilenameIndex.getFilesByName(project,name,GlobalSearchScope);类似于IDEFindUsages操作Query
