組件化解耦 框架--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 / 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
信號量
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章