Skip to content

Latest commit

 

History

History
123 lines (82 loc) · 3.46 KB

组件提供外部服务.md

File metadata and controls

123 lines (82 loc) · 3.46 KB

注意

请 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);
    }

这样,组件对外提供服务的实现方案就搞定了。