框架的API设计

框架的API设计

1. 目的

设计的目的是服务代码编写的时候无论在何处,只需要简单的调用框架API即可获取资源,无需其他任何设置。
例如在数据转发服务的代码中使用Context.logger() 返回是的数据转发服务的日志,而在管控服务中调用Context.logger()返回的是管控服务的日志。

2. 思考

  1. 不同的服务之间的资源不同,所以肯定有一个Map用来装着不同服务的资源,Map的索引即是服务的唯一索引。
  2. 同一个服务下,任何地方能直接获取到自己服务的资源,这也意味着在服务的任何地方都保存着当前服务的唯一索引。

我们首先想到的是ThreadLocal,但是同一个服务下运行着多个线程,意味着每当新开一个线程的时候需要手动添加ThreadLocal,因此此办法的效率太低。
解决办法:

不同的服务之间,除了服务的主键id不同以外,每个服务都有自己ClassLoader,因此ClassLoader可以作为服务的索引,每个线程都有自己的ContextClassLoader,当前线程新运行的子线程会直接继承父线程的ContextClassLoader,因此我们只需要在服务的启动线程设置好ContextClassLoader,服务在此线程上开启的新线程均会继承相同的ContextClassLoader,这样就实现了在一个服务的任何地方都可以通过Thread.currentThread().getContextClassLoader()来获取当前服务的索引。

public class Context{
    private static Map<ClassLoader,IResource> map=new ConcurrentHashMap<>();

    //将新的资源注册到上下文中
    protected static void register(ClassLoader loader,IResource resource){
        map.put(loader,resource);
    }

    //获取当前线程所在服务的资源
    private static IResource getResource(){
        return map.get(Thread.getCurrentThread().getContextCLassLoader();
    }

    //获取当前线程所在服务的日志
    public static ILogger logger(){
        return getResource().getILogger();
    }

    ...//获取其他资源
}

3. 其他注意事项

  • 因为服务的索引是Classloader,所以在服务的启动的时候必须单独开一个新的线程,将此线程的ContextClassLoader设置为服务的ClassLoader,并且此线程不会再被其他线程使用到。
  • 因为只有子线程才会继承父类的ClassLoader。所以服务只能用自己的线程池,不同的服务之间不能共用一个线程池,否则会造成资源使用混乱。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值