注意与乐视项目的组件化进行对比,乐视项目的组件化的相关知识,书面文档待整理,留作TODO。
背景
业务快速发展,版本不断的迭代,业务模块也在不断的增加,而且每个模块的代码也会越来越多,代码在垂直和水平方向上耦合都比较严重,同时也要维护lite版本,每次业务迭代lite版本代码的合并也是很痛苦的事情,基于上述考虑,我们要实施业务组件化。我们最终的目的是使每个业务模块都类似一个具备独立运行的U盘,即插即用,同时结合插件化框架减小包的体积,这就是我们进行业务组件化的初衷也是我们最终想要达到的一个目的。
组件化后能解决什么问题
一、业务模块独立,模块之间互不直接耦合
二、配合插件化框架,减小包的体积
三、开发团队的规模也会越来越大,组件化后,不同的组件由不同的工程师来负责,解决app开发过程中的开发与协作的问题。
组件化实施过程需要解决什么问题
一、组件间的耦合性:各个业务组件之间没有直接依赖关系即不依赖具体的实现,组件之间依赖抽象。
二、业务组件之间通信:组件内基本上保持原来的调用方式;组件之间的通信通过服务管理中心。
三、基于上述两点,我们需要一个基础的服务管理框架解决模块间的耦合和通信问题
实施方法: 组件化后由app壳工程提供统一的入口,一个项目工程拆分成若干个组件工程,由壳工程集成需要引入的业务组件,每个业务独立的组件向下依赖公共库,如下左图。各个独立的业务组件之间的调用依赖关系,通过服务管理中心调度他们之间的依赖关系,如右图。
tips1:组件化实施第一期通过服务管理中心解决业务组件间的水平依懒关系(面向接口编程思想,依懒抽象,不依懒具体实现)。当然公共库也存在水平依懒问题,由于公共库比较稳定,变动也不大,公共库间的依懒还保持现状。
tips2:业务组件依懒公共库直接以maven库形式导入,直接调用公共库中的方法即可,目前暂不封装公共库的Service到服务管理中心。


SM组件化框架
项目按照相关的业务进行模块化拆分后,模块以Service的形式对外公开模块的能力,外部通过接口调用服务的方法,模块内部是接口具体的实现,ServiceManager根据接口上Autowired注解来查找具体的服务,并通过反射实例化具体的对象。调用流程图如下:

接入方式
每个功能Module,由pi module和pm module两个Module组成,其中pi存放了接口,pm中存放了pi中接口的部分实现。
PI(Project Interface)
1
| @Module(packageName = "com.ss....pm_xx",className="com.ss.android.....XXServiceModule")
|
,注解注入了包名,类名,对应着真正的业务类。
- IXXServiceDepend 接口: 本模块所需要依赖其他模块的接口。
PM(Project Module)
功能实现Module。
XXService,实现了IXXService接口中的方法的单例类。实现的IXXService接口中的方法是暴露给其他Module使用的,XXService也可以加一些非IXXService接口中的方法,这些方法不会暴露给外部,仅供自己使用。
XXServiceModule,对外暴露服务的帮助类(具体实现原理见源码分析),应用在IXXService接口上的注解中的className的值,对应的就是这个类,XXServiceModule通用实现如下:
1 2 3 4 5 6 7 8 9 10
| public class CircleServiceModule implements IModule {
private List<ICreator<?>> updateServer = new ArrayList<>();
@Override public List<ICreator<?>> getServiceCreators() { updateServer.add(new ServiceCreator<>(CircleService.getInstance(), ICircleService.class)); return updateServer; } }
|
真正的业务类,大体架构像高阶版的 MVP 模式,使用 lifecycle 做 ViewModel 和 View 之间的通信。具体细节请看微观架构分析。
有一些网络请求类,工具类,埋点类等。
SM组件化框架源码分析
Module注解类,用来标记业务Module的PI Module中的IXXService接口,主要用来指明PM Module中的XXServiceModule类的位置。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) public @interface Module { /** * @return 服务所在Module的class全名 */ String className() default "";
/** * 返回服务所在Module的包名,不同的Module的包名必须不同,不能有一个包名下存在两个不同Module的情况 * * @return 服务所在Module的包名 */ String packageName() default "";
/** * @return 服务所在Module是否由插件提供 */ boolean isPlugin() default false ;
/** * @return 服务所在Module由插件提供时的插件包名 */ String pluginPackageName() default "";
/** * @return 服务所在Module由插件提供时的插件最小版本 */ int dependPluginMinVersion() default 0; }
|
服务包装类ICreator:
1 2 3 4 5
| public interface ICreator<T> { public T get(Object... args);
public Class<T> getKey(); }
|
服务包装类ICreator的实现类ServiceCreator,主要用来包装XXService,mInstance赋值为XXService,mCls赋值为IXXService:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| public class ServiceCreator<T> implements ICreator<T> { private T mInstance; private Class<T> mCls;
public ServiceCreator(T instance, Class<T> cls) { mInstance = instance; mCls = cls; }
@Override public T get(Object... args) { return mInstance; }
@Override public Class<T> getKey() { return mCls; } }
|
暴露服务的辅助接口IModule。
1 2 3
| public interface IModule { List<ICreator<?>> getServiceCreators(); }
|
Module包装类ModuleInfo,通过反射创建IModule的实现类的实例,从而将IModule的实现类中的ICreator<?>注册到ServiceManager的Map中。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49
| class ModuleInfo { public static final String TAG = ModuleFactory.TAG;
private IModule module;
private String className;
private boolean isInstanced;
public ModuleInfo(String className) { this.className = className; }
boolean tryInstanceModule() { if (isInstanced || TextUtils.isEmpty(className)) { return isInstanced; } try { if (module == null) { final Class contextClass = Class.forName(className); final Object instance = contextClass.newInstance(); if (instance instanceof IModule) { module = (IModule) instance; } } if (module != null) { // 注册当前Module提供的所有ServiceCreator final List<ICreator<?>> serviceCreators = module.getServiceCreators(); if (serviceCreators != null && !serviceCreators.isEmpty()) { for (ICreator<?> serviceCreator : serviceCreators) { if (serviceCreator == null) { continue; } ServiceManager.addServiceCreator(serviceCreator); } isInstanced = true; } } } catch (Throwable e) { isInstanced = false; e.printStackTrace(); } return isInstanced; }
boolean isInstanced() { return isInstanced; } }
|
IModule实现类的工厂类ModuleFactory,用来管理IModule的实现类。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64
| public class ModuleFactory {
static final String TAG = "ModuleFactory";
private static volatile ModuleFactory sInstance;
final Map<String, ModuleInfo> mModuleInfoMap = new ConcurrentHashMap<>();
private static IPluginDependListener mPluginDependListener; private static Application mApplication;
public static ModuleFactory init(ConfigBuilder configBuilder) { if(configBuilder == null || configBuilder.mPluginListener == null || configBuilder.mApplication == null){ throw new IllegalArgumentException("params cannot be null"); } if (sInstance == null) { synchronized (ModuleFactory.class) { if (sInstance == null) { sInstance = new ModuleFactory(); mPluginDependListener = configBuilder.mPluginListener; mApplication = configBuilder.mApplication; } } } return sInstance; }
static ModuleFactory getModuleFactory() { return sInstance; }
private ModuleFactory() {
}
public boolean tryInitModule(String packageName, String className, boolean isPlugin, String pluginPackageName, int dependPluginMinVersion) { if (TextUtils.isEmpty(packageName) || TextUtils.isEmpty(className) || (isPlugin && (TextUtils.isEmpty(pluginPackageName) || mPluginDependListener == null))) { return false; } if(isPlugin && !mPluginDependListener.checkPluginStatus(pluginPackageName,dependPluginMinVersion)){ return false; } ModuleInfo moduleInfo = mModuleInfoMap.get(packageName); if (moduleInfo == null) { moduleInfo = new ModuleInfo(className); mModuleInfoMap.put(packageName, moduleInfo); } return moduleInfo.isInstanced() || moduleInfo.tryInstanceModule(); }
public static class ConfigBuilder{ private IPluginDependListener mPluginListener; private Application mApplication; public ConfigBuilder setPluginListener(IPluginDependListener pluginListener){ this.mPluginListener = pluginListener; return this; }
public ConfigBuilder setApplication(Application application){ this.mApplication = application; return this; } } }
|
服务管理类ServiceManager,用来管理服务。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62
| public class ServiceManager {
static final String TAG = "ServiceManager";
private static final Map<Class<?>, ICreator<?>> sServiceCreatorMap = new ConcurrentHashMap<>();
static void addServiceCreator(ICreator<?> serviceCreator) { if (serviceCreator == null) { return; } final Class<?> key = serviceCreator.getKey(); if (key == null) { return; } sServiceCreatorMap.put(key, serviceCreator); }
public synchronized static <T> T get(Class<T> cls,Object... args) { if(!cls.isInterface()){ throw new IllegalArgumentException(String.format("cls %s should be a interface class",cls.getCanonicalName())); } ICreator<T> serviceCreator = (ICreator<T>) sServiceCreatorMap.get(cls); if (serviceCreator != null) { return serviceCreator.get(args); } else if (cls.isAnnotationPresent(Module.class)) { try { final Module module = cls.getAnnotation(Module.class); if (module == null) { return null; } String packageName = module.packageName(); String className = module.className(); String pluginPackageName = module.pluginPackageName(); int dependPluginMinVersion = module.dependPluginMinVersion(); boolean isPlugin = module.isPlugin(); if (TextUtils.isEmpty(packageName) || TextUtils.isEmpty(className)) { return null; } if(isPlugin && TextUtils.isEmpty(pluginPackageName)){ return null; } final ModuleFactory moduleFactory = ModuleFactory.getModuleFactory(); if (moduleFactory == null) { return null; } // module初始化过程会将自己提供的所有service的servicecreator注册到sServiceCreatorMap if (!moduleFactory.tryInitModule(packageName, className, isPlugin, pluginPackageName, dependPluginMinVersion)) { return null; } serviceCreator = (ICreator<T>) sServiceCreatorMap.get(cls); if (serviceCreator == null) { return null; } return serviceCreator.get(args); } catch (Throwable e) { e.printStackTrace(); } } return null; } }
|
上一篇:应用首帧耗时开始时间
下一篇:Instant Run的原理