元件化解耦,SCM
SCM - 元件化通訊工具
一切皆元件,當每個元件可看成一個微服務,元件化專案才會真正解耦
元件化介紹:
通過一個類比的例子來介紹元件化
隨著業務的複雜度增大,業務線縱橫交錯,往往牽一髮而動全身。
我們希望業務程式碼也能像一部智慧手機。
入口模組:應用桌面圖示,更像是home模組,只提供入口;
業務模組:通過appstore,下載我們需要的app,每個app(模組)職責分明,鬧鐘,簡訊,電話......;
當某個模組需求變化,並不想影響到其他業務線的大規模變動,只用更新當前app(模組);
甚至 -- 我的模組、元件可以發到 appstore 給其他手機使用(外掛化),每個應用可以資源互動(元件通訊),可以增量更新…
所以:
一切皆元件,
每個模組就是一個微服務,通過 rest api 來訪問,用完即走。
SCM介紹:
SCM就是用來定義api介面(通過註解在編譯期生成服務登錄檔),通過請求(SCM.req),來拿到對應服務(action)的響應結果(ScCallback)的工具
SCM 不支援 Install Run
1: 通過註解註冊 @Action(name = "") 宣告服務 類實現ScAction
2: 一個 Action 對應一個微服務
3: 通過對註解 Compiler 編譯期生成 -> 服務登錄檔
4: Application 初始化 執行期掃描服務、快取登錄檔
5: 呼叫 SCM.req(String action,Callback A) 呼叫服務, 真正實現解耦
action ---> module actionTable ---> scmTable

SCM.png
使用:
1:根專案root-project的build.gradle
repositories { ... maven { url"https://dl.bintray.com/woaigmz/SCM" } }
2:你的每個module的build.gradle
defaultConfig { ... javaCompileOptions { annotationProcessorOptions { arguments = [KEY_MODULE_NAME:"Main"] includeCompileClasspath true } } } ... dependencies { compile 'com.woaigmz.scm:scm-api:0.0.4' compile 'com.woaigmz.scm:scm-annotation:0.0.4' annotationProcessor 'com.woaigmz.scm:scm-compiler:0.0.4' }
3:初始化
public class App extends Application { @Override public void onCreate() { super.onCreate(); //對應每個module的 arguments = [KEY_MODULE_NAME:"Main"] SCM.get().scanningSCMTable(new String[]{"Main", "Home"}); } }
4:定義 Service(@Action)為 module-home/actions/HomeLoadConfigAction,為 home-module 提供給外界的api
//home-module/actions/HomeLoadConfigAction @Action(name = "LoadConfig") public class HomeLoadConfigAction implements ScAction { @Override public void invoke(Context context, String param, ScCallback callback) { //模擬載入網路資料 DataProvider.getConfig(callback); } } //home-module/actions/HomeEntryAction @Action(name = "HomeEntry") public class HomeEntryAction implements ScAction { @Override public void invoke(Context context, String param, ScCallback callback) { Intent intent = new Intent(); intent.setClass(context, HomeActivity.class); context.startActivity(intent); callback.onCallback(true, "HomeEntryAction:我把HomeActivity打開了", ""); } }
//除頁面跳轉之外,大部分都是非同步,業務情景不同,本框架不提供非同步轉同步,開發者自己實現
5:請求:由action-name通過 SCM.req()方法在module-app / ofollow,noindex">MainActivity 獲取 module-home/actions 下的服務action
private WeakHandler h = new WeakHandler(new Handler.Callback() { @Override public boolean handleMessage(Message msg) { String s = (String) msg.obj; Toast.makeText(MainActivity.this, s, Toast.LENGTH_SHORT).show(); tvLoadConfig.setText(s); return false; } }); //通過Action :"LoadConfig"請求; 響應:ScCallback 返回的是子執行緒進行的網路請求結果要用handler private void loadConfigByHomeModule() { try { SCM.get().req(MainActivity.this, "LoadConfig", new ScCallback() { @Override public void onCallback(boolean b, String data, String tag) { if (b) { Message obtain = Message.obtain(); obtain.obj = data; if (h != null) { h.sendMessage(obtain); } else { Toast.makeText(MainActivity.this, "WeakHandler has been Gc", Toast.LENGTH_SHORT).show(); } } } }); } catch (Exception e) { Log.e(Constants.SCM, e.getMessage()); } } //跳轉到Home-module/view/HomeActivity try { SCM.get().req(MainActivity.this, "HomeEntry", new ScCallback() { @Override public void onCallback(boolean b, final String data, String tag) { if (b) Toast.makeText(MainActivity.this, data, Toast.LENGTH_SHORT).show(); } }); } catch (Exception e) { Log.e(Constants.SCM, e.getMessage()); }
想法:
想到 java 後臺通過action來定義一個介面 ,servlet裡的 req,res,有更好的歡迎issue,star fork 。。。
具體實現思路可用參考專案: SCM地址:
註解工具的作用:action 加到登錄檔,通過 annotationProcessor 編譯時註解,編譯期生成(SCMTable)表註冊
註解工具連結: ActionProcessor.java
SCM優點:
1:跨程序,通過傳遞的 json/string 字元實現類似 CC 的通過socket協議傳遞字元流
2:通過action對應的name,反射呼叫Action的invoke方法,實現解耦合 類似元件化專案 ModularizationArchitecture (aidl + service跨程序)
3:登錄檔簡潔易懂,想到了R檔案的生成,public static final "$actionName" = "@action對應action的實際包名"
4:只要原來的協議不變(@action(name="XXX"))程式碼重構不會對action有影響
5:編譯期生成SCMTable提高了掃描整個包的效能
maven上傳命令:
gradle install / gradlew bintrayUpload 上傳專案到 maven
檢視有焦點的activity的包名
linux:adb shell dumpsys activity | grep "mFocusedActivity" / windows:adb shell dumpsys activity | findstr "mFocusedActivity"
不提供非同步轉通過方法,因為除了頁面跳轉,一般的action都是耗時操作,處理方式留給開發者具體問題具體對待,
幾種非同步轉同步: wait / notify 條件鎖 Future CountDownLatch/CyclicBarrier Handler 訊號量