Intellij IDEA 插件開發秘籍


>>>> IntelliJ IDEA 與 IntelliJ Platform

IntelliJ IDEA 簡稱 IDEA,是 Jetbrains 公司旗下的一款 JAVA 開發工具,支持 Java、Scala、Groovy 等語言的開發,同時具備支持目前主流的技術和框架,擅長於企業應用、移動應用和 Web 應用的開發,提供了豐富的功能,智能代碼助手、代碼自動提示、重構、J2EE支持、各類版本工具(git、svn等)、JUnit、CVS整合、代碼分析、 創新的GUI設計等。

IntelliJ Platform 是一個構建 IDE 的開源平台,基於它構建的 IDE 有 IntelliJ IDEA、WebStorm、DataGrip、以及 Android Studio 等等。IDEA 插件也是基於 IntelliJ Platform 開發的。

>>>> 開發環境搭建

本章節介紹 IDEA 插件開發環境的搭建與配置

>>>> 一、開發工具

開發工具使用 Intellij IDEA,下載地址:https://www.jetbrains.com/idea/

IDEA 分為兩個版本:

  • 社區版(Community):完全免費,代碼開源,但是缺少一些旗艦版中的高級特性
  • 旗艦版(Ultimate):30天免費,支持全部功能,代碼不開源

開發IDEA的插件推薦使用社區版,因為社區版是開源的,在開發插件的時候,可以調試源代碼。

>>>> 二、啟用 Plugin DevKit

Plugin DevKit 是 IntelliJ 的一個插件,它使用 IntelliJ IDEA 自己的構建系統來為開發 IDEA 插件提供支持。開發 IDEA 插件之前需要安裝並啟用 Plugin DevKit 。

打開 IDEA,導航到 Settings | Plugins,若插件列表中沒有 Plugin DevKit,點擊 Install JetBrains plugin,搜索並安裝。

>>>> 三、配置 IntelliJ Platform Plugin SDK

IntelliJ Platform Plugin SDK 就是開發 IntelliJ 平台插件的SDK, 是基於 JDK 之上運行的,類似於開發 Android 應用需要 Android SDK。

  1. 導航到 File | Project Structure,選擇對話框左側欄 Platform Settings 下的 SDKs
  2. 點擊 + 按鈕,先選擇 JDK,指定 JDK 的路徑;再創建 IntelliJ Platform Plugin SDK,指定 home path 為 IDEA 的安裝路徑,如圖
  1. 創建好 IntelliJ Platform Plugin SDK 后,選擇左側欄 Project Settings 下的 Projects,在 Project SDK 下選擇剛創建的 IntelliJ Platform Plugin SDK。

>>>> 四、設置源碼路徑(可選)

  1. 查看 build 號:打開 IDEA,Help | About,查看版本號及 build 號
  2. IDEA Community 源碼(https://github.com/JetBrains/intellij-community/):切換到與 build 號相同的分支,點擊 Clone or download 按鈕,選擇 Download ZIP

>>>> 五、Sandbox

IntelliJ IDEA 插件以 Debug/Run 模式運行時是在 SandBox 中進行的,不會影響當前的 IntelliJ IDEA;但是同一台機器同時開發多個插件時默認使用的同一個 sandbox,即在創建 IntelliJ Platform SDK 時默認指定的 Sandbox Home

如果需要每個插件的開發環境是相互獨立的,可以創建多個 IntelliJ Platform SDK,為 Sandbox Home 指定不同的目錄 。

>>>> 開發一個簡單插件

本篇介紹插件的創建、配置、運行、打包流程,以及 action

>>>> 一、創建一個插件工程

選擇 File | New | Project,左側欄中選擇 IntelliJ Platform Plugin 工程類型

點擊 Next,設置工程名稱及位置,點擊 Finish 完成創建。可以到 File | Project Structure 來自定義工程設置。

>>>> 二、插件工程結構

插件工程內容:

PluginDemo/
    resources/ META-INF/ plugin.xml src/ com/foo/... ... ...
  • src 實現插件功能的classes
  • resources/META-INF/plugin.xml 插件的配置文件,指定插件名稱、描述、版本號、支持的 IntelliJ IDEA 版本、插件的 components 和 actions 以及軟件商等信息。

>>>> 三、plugin.xml

下面示例描述了可在 plugin.xml 文件配置的主要元素:

<idea-plugin> <!-- 插件名稱,別人在官方插件庫搜索你的插件時使用的名稱 --> <name>MyPlugin</name> <!-- 插件唯一id,不能和其他插件項目重復,所以推薦使用com.xxx.xxx的格式 插件不同版本之間不能更改,若沒有指定,則與插件名稱相同 --> <id>com.example.plugin.myplugin</id> <!-- 插件的描述 --> <description>my plugin description</description> <!-- 插件版本變更信息,支持HTML標簽; 將展示在 settings | Plugins 對話框和插件倉庫的Web頁面 --> <change-notes>Initial release of the plugin.</change-notes> <!-- 插件版本 --> <version>1.0</version> <!-- 供應商主頁和email--> <vendor url="http://www.jetbrains.com" email="support@jetbrains.com" /> <!-- 插件所依賴的其他插件的id --> <depends>MyFirstPlugin</depends> <!-- 插件兼容IDEA的最大和最小 build 號,兩個屬性可以任選一個或者同時使用 官網詳細介紹:http://www.jetbrains.org/intellij/sdk/docs/basics/getting_started/build_number_ranges.html--> <idea-version since-build="3000" until-build="3999"/> <!-- application components --> <application-components> <component> <!-- 組件接口 --> <interface-class>com.foo.Component1Interface</interface-class> <!-- 組件的實現類 --> <implementation-class>com.foo.impl.Component1Impl</implementation-class> </component> </application-components> <!-- project components --> <project-components> <component> <!-- 接口和實現類相同 --> <interface-class>com.foo.Component2</interface-class> </component> </project-components> <!-- module components --> <module-components> <component> <interface-class>com.foo.Component3</interface-class> </component> </module-components> <!-- Actions --> <actions> ... </actions> <!-- 插件定義的擴展點,以供其他插件擴展該插件 --> <extensionPoints> ... </extensionPoints> <!-- 聲明該插件對IDEA core或其他插件的擴展 --> <extensions xmlns="com.intellij"> ... </extensions> </idea-plugin>

>>>> 四、創建 Action

一個 Action 表示 IDEA 菜單里的一個 menu item 或工具欄上的一個按鈕,通過繼承 AnAction class 實現,當選擇一個 menu item 或點擊工具欄上的按鈕時,就會調用 AnAction 類的 actionPerformed 方法。

實現自定義 Action 分兩步:

  • 定義一個或多個 action
  • 注冊 action,將 item 添加到菜單或工具欄上

 

 

1、定義 Action

定義一個 Java class,繼承 AnAction 類,並重寫 actionPerformed 方法, 如

public class TextBoxes extends AnAction { public void actionPerformed(AnActionEvent event) { Project project = event.getData(PlatformDataKeys.PROJECT); Messages.showInputDialog( project, "What is your name?", "Input your name", Messages.getQuestionIcon()); } }

 

2、注冊 Action

在 plugin.xml 文件的 <actions> 元素內注冊

<actions> <group id="MyPlugin.SampleMenu" text="Sample Menu" description="Sample menu"> <add-to-group group-id="MainMenu" anchor="last" /> <action id="Myplugin.Textboxes" class="Mypackage.TextBoxes" text="Text Boxes" description="A test menu item" /> </group> </actions>
  • <action> 元素會定義一個 action,指定 action 的 id、實現類、顯示文本、描述
  • <group> 元素會定義一個 action group(多個action),設置 action group 的 id、文本、描述
  • <add-to-group> 元素指定其外部 action 或 action group 被添加到的位置

上面示例會定義一個被添加到 IDEA 主菜單的最后面的 “SampleMenu” 的菜單,點擊該菜單將彈出一個 “Text Boxes” item,如圖

點擊該 “Text Boxes” item,彈出一個提示輸入名字的對話框

更多 action 信息請移步 IntelliJ Platform Action System(http://www.jetbrains.org/intellij/sdk/docs/basics/action_system.html)

3、快速創建 Action

IntelliJ Platform 提供了 New Action 向導,它會幫助我們創建 action class 並配置 plugin.xml 文件:

在目標 package 上右鍵,選擇 New | Plugin DevKit | Action:

在彈出的對話框中填充下列字段,然后點擊 OK:

  • Action ID: action 唯一 id,推薦 format: PluginName.ID
  • Class Name: 要被創建的 action class 名稱
  • Name: menu item 的文本
  • Description: action 描述,toolbar 上按鈕的提示文本,可選
  • Add to Group:選擇新 action 要被添加到的 action group(Groups, Actions)以及相對其他 actions 的位置(Anchor)
  • Keyboard Shortcuts:指定 action 的第一和第二快捷鍵

注意:該向導只能向主菜單中已存在的 action group 或工具欄上添加 action,若要創建新的 action group,請參考前面的內容。

>>>> 五、運行調試插件

運行/調試插件可直接在 IntelliJ IDEA 進行,選擇 Run | Edit Configurations...,若左側欄沒有 Plugin 類型的 Configuration, 點擊右上角 + 按鈕,選擇 Plugin 類型, 如圖

Use classpath of module 選擇要調試的 module,其余配置一般默認即可;切換到 Logs 選項卡,如果勾選了 idea.log,運行插件時 idea.log 文件的內容將輸出到 idea.log console。

運行插件點擊工具欄上

按鈕即可,IntelliJ IDEA 會另啟一個裝有該插件的 IDEA 窗口

>>>> 六、打包安裝插件

1、打包插件

選擇 Build | Prepare Plugin Module ‘module name’ for Deployment 來打包插件:

插件包位置:一般在工程根目錄下

如果插件沒有依賴任何 library,插件會被打包成一個 .jar,否則會被打包成一個 .zip,zip 中包含了所有的插件依賴

jar類型的插件包:

PluginDemo.jar/ com/foo/... ... ... META-INF/ plugin.xml

zip類型的插件包:

PluginDemo.zip/ lib/ libfoo.jar libbar.jar PluginDemo.jar/ com/foo/... ... ... META-INF/ plugin.xml

2、安裝插件

  • 導航到 File | Settings | Plugins 頁面,點擊 Install plugin from disk...
  • 選擇插件包的位置,點擊 OK
  • 在插件列表中,勾選插件名字后面的 check-box 來啟用插件,點擊 OK
  • 重啟 IDEA

Install JetBrains plugin... 從 JetBrains 倉庫(https://plugins.jetbrains.com/)中安裝插件

Browse repositories... 添加並管理自己的倉庫

>>>> Components

IntelliJ IDEA 的組件模型是基於 PicoContainer(https://www.cnblogs.com/yaoxiaohui/archive/2009/03/08/1406228.html) 的,組件都包含在這些容器中,但容器有三種級別:application container,project container 以及 module container。application container 可以包含多個 project container,而 project container 可以包含多個 module container。

>>>> 一、Components 類型

Components 是插件開發的基礎,Components 有三種類型:

>>>> 二、注冊 Components

components 需要配置在 plugin.xml 中,並指定 interface 和 implementation,interface 類用於從其他組件中檢索組件,implementation 類用於實例化組件。示例:

//創建一個 application level component
public interface Component1 extends ApplicationComponent { } public class Component1Impl implements Component1 { @Override public String getComponentName() { return "PluginDemo.Component1"; } }

plugin.xml

<application-components> <component> <interface-class>com.example.test.Component1</interface-class> <implementation-class>com.example.test.Component1Impl</implementation-class> </component> </application-components>

注意:

  1. 一個 interface-class 不能有多個 implementation-class,如下圖:
  1. 若組件沒有創建 interface 類,而是直接實現了 ApplicationComponent 等接口,interface 和 implementation 可以指定為同一個類。
  2. 每一個組件都應該有一個唯一的名字,通過 getComponentName() 返回,推薦使用 <plugin_name>.<component_name> 格式。

>>>> 三、Component 周期方法

ApplicationComponent 的生命周期方法:

//構造方法
public constructor(){ } //初始化 public void initComponent() { } public void disposeComponent() { }

ProjectComponent 的生命周期方法:

//構造方法
public constructor(){ } //通知一個project已經完成加載 public void projectOpened() { } public void projectClosed() { } //執行初始化操作以及與其他 components 的通信 public void initComponent() { } //釋放系統資源或執行其他清理 public void disposeComponent() { }

ModuleComponent 的生命周期方法:

ModuleComponent 的生命周期方法中比 ProjectComponent 多一個 moduleAdded(),用於通知 module 已經被添加到 project 中。

>>>> 四、Component 加載

Application 級別的 components 在 IDEA 啟動時加載,Project 和 Module 級別的 components 在項目啟動時共同加載。

一個組件加載過程:

  1. 創建:調用構造方法
  2. 初始化:調用 initComponent() 方法
  3. 如果是 Project 組件,會調用 projectOpened() 方法; 如果是 Module 組件,會依次調用 moduleAdded()projectOpened() 方法

如果 component 在加載時需要用到其他 component,我們只需在該 component 的構造方法的參數列表聲明即可,在這種情況下,IntelliJ IDEA 會按正確的順序實例化所依賴的 component。

示例:

public class MyComponent implements ApplicationComponent { private final MyOtherComponent otherComponent; public MyComponent(MyOtherComponent otherComponent) { this.otherComponent = otherComponent; } ... }

>>>> 五、Component 卸載

一個組件卸載過程:

  1. 如果是 Project 或 Module 組件,調用 projectClosed()
  2. 接下來 disposeComponent() 將被調用

>>>> 六、Component 容器

前面我們提到有三種不同的容器,application container 實現 Application 接口; project container 實現 Project 接口;

module container 實現 Module 接口。每一個容器都有自己的方法去獲取容器內的 component。

獲取 application 容器及其內部的組件:

//獲取application容器
Application application = ApplicationManager.getApplication(); //獲取application容器中的組件 MyComponent myComponent = application.getComponent(MyComponent.class);

獲取 project / module 容器及其內部的組件:

在 component 構造方法的參數列表中聲明:

public class MyComponent implements ProjectComponent { Project project; public MyComponent(Project project){ this.project = project; } public void initComponent() { OtherComponent otherComponent = project.getComponent(OtherComponent.class); } }

在這個例子中,組件在構造方法中獲取了容器對象,將其保存,然后在 component 其他地方進行引用。但是需要注意一點:

Be careful when passing this reference to other components (especially >application-level ones). If an application- level component does not release the reference, but saves it inside itself, >all the resources used by a project or module will not be unloaded from the memory on the project closing.

或者從action的事件處理的context的獲取:

public class TextBoxes extends AnAction { @Override public void actionPerformed(AnActionEvent anActionEvent) { DataContext dataContext = e.getDataContext(); Project project = (Project)dataContext.getData(DataConstants.PROJECT); Module module =(Module)dataContext.getData(DataConstants.MODULE); } }

>>>> Extensions and Extension Points

如果插件需要擴展 IDEA Platform 或 其他插件的功能,或為其他插件提供可以擴展自己的接口,那么就要用到 extensions 和 extension points,用於與 IDEA 和其他插件交互。

>>>> 一、Extension points

extension point 用於數據信息擴展,使其他插件可以擴展本插件的功能,可通過plugin.xml 的 <extensionPoints> 元素聲明,如下示例:

<extensionPoints> <!--使用beanClass聲明--> <extensionPoint name="MyExtensionPoint1" beanClass="MyPackage.MyBeanClass" area="IDEA_APPLICATION"> <with attribute="implementationClass" implements="MyPackage.MyAbstractClass"/> </extensionPoint> <!--使用interface聲明--> <extensionPoint name="MyExtensionPoint2" interface="MyPlugin.MyInterface" area="IDEA_PROJECT" /> </extensionPoints>
  • name 指定 extension point 的名字,當其他插件擴展該extensionPoint時,需要指定該name
  • area 有三種值,IDEAAPPLICATION,IDEAPROJECT,IDEA_MODULE,指定extension point的級別
  • interface 指定需要擴展此 extension point 的插件必須要實現的接口
  • beanClass 指定一個類,該類有一個或多個被 @Attribute (https://upsource.jetbrains.com/idea-ce/file/idea-ce-d00d8b4ae3ed33097972b8a4286b336bf4ffcfab/xml/dom-openapi/src/com/intellij/util/xml/Attribute.java)注解的屬性
  • 聲明 extension point 有兩種方式,指定 beanClass 或 interface
  • 如果某個屬性需要是某個類的子類,或某個接口的實現類,需要通過 <with> 指明類名或接口名。

示例上述代碼中的 MyExtensionPoint1 的 beanClass:

public class MyBeanClass extends AbstractExtensionPointBean { @Attribute("key") public String key; @Attribute("implementationClass") public String implementationClass; ... }

>>>> 二、Extension

如果插件需要擴展 IntelliJ Platform 或其他插件的功能,需要聲明一個或多個 extension。

  1. 設置 <extensions>defaultExtensionNs 屬性 若是擴展 IntelliJ Platform,設為 com.intellij 若是擴展其他插件,則設為 pluginId
  2. 指定要擴展哪個 extension point內部的子標簽的名字必須與 extension point 的 name 屬性相同
  3. 如果 extension point
  • 是通過 interface 聲明的,那么使用 implementation 屬性指明 interface 的實現類
  • 是通過 beanClass 聲明的,那么就要為 beanClass 中被 @Attribute 注解的屬性指定屬性值

示例:

<!-- 擴展 interface 聲明的 extensionPoint --> <extensions defaultExtensionNs="com.intellij"> <appStarter implementation="MyPackage.MyExtension1" /> <applicationConfigurable implementation="MyPackage.MyExtension2" /> </extensions> <!-- 擴展 beanClass 聲明的 extensionPoint --> <extensions defaultExtensionNs="pluginId"> <MyExtensionPoint1 key="keyValue" implementationClass="MyPackage.MyClassImpl"></MyExtensionPoint1> </extensions>

插件的 service 的實現就是擴展 IDEA Platform 的 applicationServiceprojectService 兩個 extension points

>>>> 三、獲取 extension points

IntelliJ Platform 的 extension points:

  • LangExtensionPoints.xml(https://upsource.jetbrains.com/idea-ce/file/idea-ce-d00d8b4ae3ed33097972b8a4286b336bf4ffcfab/platform/platform-resources/src/META-INF/LangExtensionPoints.xml)
  • PlatformExtensionPoints.xml(https://upsource.jetbrains.com/idea-ce/file/idea-ce-d00d8b4ae3ed33097972b8a4286b336bf4ffcfab/platform/platform-resources/src/META-INF/PlatformExtensionPoints.xml)
  • VcsExtensionPoints.xml(https://upsource.jetbrains.com/idea-ce/file/idea-ce-d00d8b4ae3ed33097972b8a4286b336bf4ffcfab/platform/platform-resources/src/META-INF/VcsExtensionPoints.xml)

其他插件的 extension points:可以從被擴展插件的 plugin.xml 文件中獲取

>>>> Service

Service 也是一種按需加載的 component,在調用 ServiceManager.getService(Class)(https://upsource.jetbrains.com/idea-ce/file/idea-ce-d00d8b4ae3ed33097972b8a4286b336bf4ffcfab/platform/core-api/src/com/intellij/openapi/components/ServiceManager.java)時才會加載,且程序中只有一個實例。

Serivce 在 IntelliJ IDEA 中是以 extension point 形式提供的,實現自己的 service 需要擴展相應 extension point。

  • applicationService: application level service
  • projectService: project level service
  • moduleService: module level service

聲明 service 時必須包含 serviceImplementation 屬性用於實例化 service, serviceInterface 屬性是可選的,可用於獲取 service 實例。

>>>> 一、創建 Service

在需要放置 service 的 package 上右鍵, New | Plugin DevKit | xxxxService,如圖

選擇相應 service,彈出如下對話框,填寫 interface 類和 implementation 類,若不勾選 Separate interface from implementation,只需填寫 implementation 類。

IntelliJ IDEA 會自動創建相應類並配置 plugin.xml 文件。

示例:

plugin.xml:

<extensions defaultExtensionNs="com.intellij"> <!-- project level service --> <projectService serviceInterface="com.example.test.service.MyProjectService" serviceImplementation="com.example.test.service.impl.MyProjectServiceImpl"/> </extensions>

生成的 service 類:

package com.example.test.service; import com.intellij.openapi.components.ServiceManager; import com.intellij.openapi.project.Project; import org.jetbrains.annotations.NotNull; public interface MyProjectService { //獲取 service 實例 static MyProjectService getInstance(@NotNull Project project) { return ServiceManager.getService(project, MyProjectService.class); } }
package com.example.test.service.impl; import com.example.test.service.MyProjectService; import com.intellij.openapi.project.Project; public class MyProjectServiceImpl implements MyProjectService { public MyProjectServiceImpl(Project project) { } }

>>>> 二、獲取 Service

MyApplicationService applicationService = ServiceManager.getService(MyApplicationService.class); //獲取 project 級別的 service,需要提供 project 對象 MyProjectService projectService = ServiceManager.getService(project, MyProjectService.class); //獲取 module 級別的 service,需要提供 module 對象 MyModuleService moduleService = ModuleServiceManager.getService(module, MyModuleService.class);

>>>> 持久化狀態

我們在使用 IDE 開始開發工作之前,總是要先在 settings 頁面進行一些設置,且每次重新打開 IDE 后這些設置仍然保留着,那么這些設置是如何保存下來的呢?

IntelliJ Platform 提供了一些 API,可以使 components 或 services 在每次打開 IDE 時仍然使用之前的數據,即持久化其狀態。

>>>> 一、PropertiesComponent

對於一些簡單少量的值,我們可以使用 PropertiesComponent,它可以保存 application 級別和 project 級別的值。

下面方法用於獲取 PropertiesComponent 對象:

//獲取 application 級別的 PropertiesComponent
PropertiesComponent.getInstance() //獲取 project 級別的 PropertiesComponent,指定相應的 project PropertiesComponent.getInstance(Project) propertiesComponent.setValue(name, value) propertiesComponent.getValue(name)

PropertiesComponent 保存的是鍵值對,由於所有插件使用的是同一個 namespace,強烈建議使用前綴來命名 name,比如使用 plugin id。

>>>> 二、PersistentStateComponent

PersistentStateComponent(https://upsource.jetbrains.com/idea-ce/file/idea-ce-d00d8b4ae3ed33097972b8a4286b336bf4ffcfab/platform/projectModel-api/src/com/intellij/openapi/components/PersistentStateComponent.java) 用於持久化比較復雜的 components 或 services,可以指定需要持久化的值、值的格式以及存儲位置。

要使用 PersistentStateComponent 持久化狀態:

  • 需要提供一個 PersistentStateComponent<T> 接口的實現類(component 或 service),指定類型參數,重寫 getState() 和 loadState() 方法
  • 類型參數就是要被持久化的類,它可以是一個 bean class,也可以是 PersistentStateComponent實現類本身。
  • PersistentStateComponent<T> 的實現類上,通過 @com.intellij.openapi.components.State 注解指定存儲的位置

下面通過兩個例子進行說明:

class MyService implements PersistentStateComponent<MyService.State> { //這里 state 是一個 bean class static class State { public String value; ... } //用於保存當前的狀態 State myState; // 從當前對象里獲取狀態 public State getState() { return myState; } // 從外部加載狀態,設置給當前對象的相應字段 public void loadState(State state) { myState = state; } }
// 這里的 state 就是實現類本身
class MyService implements PersistentStateComponent<MyService> { public String stateValue; ... public MyService getState() { return this; } public void loadState(MyService state) { XmlSerializerUtil.copyBean(state, this); } }

1、實現 State 類

a、字段要求

state 類中可能有多個字段,但不是所有字段都可以被持久化,可以被持久化的字段:

  • public 字段
  • bean 屬性:提供 getter 和 setter 方法
  • 注解(https://upsource.jetbrains.com/idea-ce/file/idea-ce-d00d8b4ae3ed33097972b8a4286b336bf4ffcfab/platform/util/src/com/intellij/util/xmlb/annotations)的私有字段:使用 @Tag, @Attribute, @Property, @MapAnnotation, @AbstractCollection 等注解來自定義存儲格式,一般在實現向后兼容時才考慮使用這些注解

這些字段也有類型要求:

  • 數字(包括基礎類型,如int,和封裝類型,如Integer)
  • 布爾值
  • 字符串
  • 集合
  • map
  • 枚舉

如果不希望某個字段被持久化,可以使用 @com.intellij.util.xmlb.annotations.Transient 注解。

b、構造器要求

state 類必須有一個默認構造器,這個構造器返回的 state 對象被認為是默認狀態,只有當當前狀態與默認狀態不同時,狀態才會被持久化。

2、定義存儲位置

我們可以使用 @State 注解來定義存儲位置

@State(name = "PersistentDemo", storages = {@Storage(value = "PluginDemo.xml")}) public class PersistentDemo implements PersistentStateComponent<PersistentDemo> { ... }

name: 定義 xml 文件根標簽的名稱

storages: 一個或多個 @Storage,定義存儲的位置

  • 若是 application 級別的組件 運行調試時 xml 文件的位置: ~/IdeaICxxxx/system/plugins-sandbox/config/options 正式環境時 xml 文件的位置: ~/IdeaICxxxx/config/options
  • 若是 project 級別的組件,默認為項目的 .idea/misc.xml,若指定為 StoragePathMacros.WORKSPACE_FILE,則會被保存在 .idea/worksapce.xml

3、生命周期

  • loadState() 當組件被創建或 xml 文件被外部改變(比如被版本控制系統更新)時被調用
  • getState() 當 settings 被保存(比如settings窗口失去焦點,關閉IDE)時,該方法會被調用並保存狀態值。如果 getState() 返回的狀態與默認狀態相同,那么什么都不會被保存。
  • noStateLoaded() 該方法不是必須實現的,當初始化組件,但是沒有狀態被持久化時會被調用

4、組件聲明

持久化組件可以聲明為 component,也可以聲明為 service

聲明為 service,plugin.xml 文件如下配置:

<extensions defaultExtensionNs="com.intellij"> <applicationService serviceImplementation="com.example.test.persisting.PersistentDemo"/> <projectService serviceImplementation="com.example.test.persisting.PersistentDemo2"/> </extensions>

代碼中獲取狀態與獲取 service 的方式一樣:

PersistentDemo persistDemo = ServiceManager.getService(PersistentDemo.class); PersistentDemo2 persistDemo2 = ServiceManager.getService(project,PersistentDemo.class);

聲明為 component,plugin.xml 文件如下配置:

<application-components> <!--將持久化組件聲明為component--> <component> <implementation-class>com.example.persistentdemo.PersistentComponent</implementation-class> </component> </application-components>

獲取狀態與獲取 component 的方式一樣:

public static PersistentComponent getInstance() { return ApplicationManager.getApplication().getComponent(PersistentComponent.class); } public static PersistentComponent getInstance(Project project) { return project.getComponent(PersistentComponent.class); }

>>>> 插件依賴

開發插件時可能會用到其他插件,可能是 IDEA 綁定的,也可能是第三方的插件。

配置插件依賴需要將插件包添加到 SDK 的 classpath 中,並在 plugin.xml 配置。

  1. 確定插件包的位置 如果插件是 IDEA 捆綁的插件,那么插件包在 IDEA 安裝目錄的 plugins/<pluginname>plugins/<pluginname>/lib 下。 如果插件是第三方或自己的,那么需要先運行一次 sandbox(其實我們在運行調試插件的時候就是在運行sandbox)並從本地或插件倉庫安裝依賴插件。 安裝好后,插件包會放在 sandbox 目錄下的 config/plugins/<pluginname>config/plugins/<pluginname>/lib, 查看 sandbox 目錄:打開 IntelliJ Platform SDK 配置頁面,其中 Sandbox Home 就是其目錄。
  2. 將插件包添加到 SDK 的 classpath 中 導航到 File | Project Structure | SDKs,選擇插件使用的 IntelliJ Platform SDK,點擊右側 + 號,在彈出的文件選擇框中選擇要依賴的插件包,點擊 OK。
  1. 配置 plugin.xml 在 plugin.xml 的 <depends> 部分添加所依賴插件的id。
<depends>org.jetbrains.kotlin</depends>

plugin id 可以從插件包的 plugin.xml 文件查看。

>>>> GUI 介紹

GUI 是 IntelliJ IDEA 提供的一個自動生成 java 布局代碼的工具,它使用 JDK 中的 Swing 控件來實現 UI 界面。

使用步驟:

  1. 配置 GUI 首先打開 Settings 對話框,選擇 Editor | GUI Designer,如圖,在 Generate GUI into: 有兩個選項,生成 class 文件或 java 代碼,我們選擇生成 java 代碼,因為建好布局后可能需要修改代碼。其他默認即可。
  1. 創建 form 文件 form 文件用於記錄界面布局。在相應的 package 上右鍵,選擇 New | GUI Form,如圖,輸入 form 文件名,一般與 java 文件名相同,點擊 OK 創建 form 與 java 文件。
  1. 編輯界面 打開 form 文件,如圖,通過拖拽控件來搭建布局。每個form文件布局的 root 控件都是一個 JPanel,可將該 root 對象傳給需要該布局的類。 注意:左下角的屬性面板,只有當填寫了 field name 屬性時該控件的對象才會被當成成員變量,否則為局部變量。
  1. 生成 java 代碼 搭建好布局后,點擊

編譯按鈕,即可生成 java 的源碼文件。 GUI 生成的方法名前后都有三個 $ 標識,當再次修改布局時,GUI 只會修改 $ 標識的方法。

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM