## 跨模块依赖注入 模块化能力支持项: - 支持跨模块依赖注入 - 支持自定义注入项的创建规则,依赖注入可自定义参数 - 支持自定义服务拦截,单模块mock调试 - 支持注入对象缓存,多次注入 只会new一次对象 ### 1.0 依赖注入 用于跨模块通信使用,核心设计思想是参考了[SOA(面向服务架构)](https://baike.baidu.com/item/%E9%9D%A2%E5%90%91%E6%9C%8D%E5%8A%A1%E6%9E%B6%E6%9E%84/8258990) 的设计方式。 具体到 Android 侧就是 AIDL 类似的实现: 例如当前有两个模块:A订单模块、B登录模块,下单需要获取用户信息。 这个业务场景就是,A需要使用获取用户信息的服务,B需要向外提供一个获取用户信息的服务。 ![TheRouter](https://s1.ax1x.com/2022/06/08/XrJc0f.jpg) #### 1.1 声明接口服务 首先声明一个接口,放入公共依赖层 ``` // 假设当前有一个用户信息获取服务 public interface IUserService { String getUserInfo(); } ``` #### 1.2 服务使用方 也就是上面例子的 A订单模块,他需要使用获取用户信息的服务 A无需关心,`IUserService`这个接口服务是谁提供的,他只需要知道自己需要使用这样的一个服务就行了。 **注**:*如果没有提供服务的提供方,`TheRouter.get()`可能返回`null`* ``` TheRouter.get(IUserService::class.java)?.getUserInfo() ``` #### 1.3 服务提供方 服务提供方需要声明一个提供服务的方法,用`@ServiceProvider`注解标记。 - 如果是 java,必须是 public static 修饰 - 如果是 kotlin,建议写成 top level 的函数 - 方法名不限 ``` /** * 方法名不限定,任意名字都行 * 返回值必须是服务接口名,如果是实现了服务的子类,需要加上returnType限定(例如下面代码) * 方法必须加上 public static 修饰,否则编译期就会报错 */ @ServiceProvider public static IUserService test() { return new IUserService() { @Override public String getUserInfo() { return "返回用户信息"; } }; } // 也可以直接返回对象,然后标注这个方法的服名是什么 @ServiceProvider(returnType = IUserService.class) public static UserServiceImpl test() { xxx } ``` ### 2.0 自定义服务拦截器 **使用场景**:单模块调试时,可能会有需要 mock 其他模块提供的服务,TheRouter 允许自定义其他模块的实现。 ``` Interceptor interceptor = new Interceptor() { @Override public T interception(Class clazz, Object... params) { if (clazz == IUserService.class) { return new IUserService(); } return null; } }; TheRouter.getRouterInject().addInterceptor(interceptor); ``` ### 3.0 服务缓存 服务提供方运行对提供的服务做配置,对于无状态的服务,尽可能使用缓存方式减少对象创建次数,而有状态的服务,则每次创建新对象保证多次调用有不会互相污染状态(例如订单状态管理、商品销售状态等服务)。 声明服务缓存只需要在 @ServiceProvider的方法上新增额外注解即可,例如下面示例代码: - **Singleton** 表示这个对象会被永久缓存,对外部调用方而言相当于这个对象声明成了单例 - **NewInstance** 表示每次都会返回新对象 **注**:*如果两个注解同时被添加,则只有`Singleton`会生效。* ``` // 注:如果两个注解同时被添加,则只有Singleton会生效。 @Singleton // 对外部调用方而言相当于这个对象声明成了单例 @NewInstance // 每次都会返回新对象 @ServiceProvider public static IUserService test() { return new IUserService() { @Override public String getUserInfo() { return "返回用户信息"; } }; } ```