请 checkout service
分支进行查看。
组件向外提供服务,由于代码隔离的原因,所以其他组件也没法使用它里面的代码,那么我们需要做的就是建立一个映射关系,比如一个字符串对应了一个服务的提供类。然后,想要获取服务的一方就可以用这个字符串来获取服务,然后使用这个服务。
几个类的关系大致如下:
组件 A,提供服务的一方
interface IService {
String NAME = "Service";
int add(int a, int b);
}
class ServiceImpl implements IService {
@Override
public int add(int a, int b) {
return a + b;
}
}
组件 A 对外提供了一个服务 IService,然后往服务管理中心里面去注册这个服务:
ServiceManager.register(IService.Name, new ServiceImpl());
这样,其他的组件就可以获取这个服务了:
组件 B,使用服务的一方
IService service = ServiceManager.getService(IService.Name);
由于 IService 是组件A 的代码,组件B 是获取不到这个类的,因该如何处理呢?这个在 组件之间公用代码下沉问题解决方案.md
里面已经介绍过几种方案了,这里就不多说了。
根据上面的流程分析,我们需要做的就是,简化组件的注册过程,因为每个服务都要自己注册的话,那么就太麻烦了。我们可以与路由跳转一样,使用注解来标记这个服务,然后自动将它添加到一个 map 中,这个 map 就是服务管理中心。
看一个具体的例子:
com.aprz.login.sdk.IUserService
public interface IUserService {
String NAME = "service/user";
User getUserInfo();
}
这里提供了一个获取用户信息的服务,然后我们看它的实现类:
com.aprz.login.sdkimpl.UserService
@Service(name = IUserService.NAME)
public class UserService implements IUserService {
@Override
public User getUserInfo() {
return UserManager.getInstance().getUser();
}
}
它的实现类,使用 @Service
注解,根据这个注解,我们自动生成如下代码:
com.aprz.brouter.services.BRouter$$Service$$login
public class BRouter$$Service$$login implements IModuleService {
@Override
public Map<String, Object> services() {
Map<String, Object> result = new HashMap<String, Object>();
result.put("service/user", new UserService());
return result;
}
}
这样,我们就可以获取该 module 里面所有的服务映射关系。
然后,我们再使用反射来收集所有的 module 里面的服务映射关系,将它们合并在一起:
com.aprz.brouter.api.service.ServiceHelper#addModuleService
public static void addModuleService(String moduleName) {
IModuleService moduleService = findModuleService(moduleName);
Map<String, Object> services = moduleService.services();
Set<Map.Entry<String, Object>> entries = services.entrySet();
for (Map.Entry<String, Object> entry : entries) {
ServiceStore.putService(entry.getKey(), entry.getValue());
}
}
其他组件获取服务,就可以根据字符串获取了:
com.aprz.brouter.api.service.ServiceHelper#getService
public static <T> T getService(String serviceName) {
return ServiceStore.getService(serviceName);
}
这样,组件对外提供服务的实现方案就搞定了。