前言
有了上一篇的Dubbo消费者初始化过程的经验,接着来看生产者初始化的过程应该会简单不少,马上进入正题。
源码
有了上一次找初始化入口ReferenceBean类的经验,这次很快就找到了对应的入口ServiceBean类,我们来看一下它的类结构
1 | public class ServiceBean<T> extends ServiceConfig<T> implements InitializingBean, DisposableBean, ApplicationContextAware, ApplicationListener, BeanNameAware |
是不是很熟悉,那么直接来看afterPropertiesSet方法
1 | public void afterPropertiesSet() throws Exception { |
这里前面一大段都是在做初始化的准备工作,真正开始进行初始化的是最后的export()方法。当然,这里有一个前提就是要满足条件! isDelay()
1 | private boolean isDelay() { |
很明显这个方法是用来控制服务是否延迟加载的,由于初始化supportedApplicationListener值就为true,因此delay默认不配时就是开启延迟加载,也就是暂不调用export()方法,那么这个方法会在哪里调用呢?答案是onApplicationEvent(ApplicationEvent event)
1 | public void onApplicationEvent(ApplicationEvent event) { |
这也是Spring中的熟面孔了,这里它监听的是ContextRefreshedEvent,当监听到刷新事件并满足isDelay() && ! isExported() && ! isUnexported()条件时,才正式调用export()方法
1 | public synchronized void export() { |
这里主要是启动了一个守护线程来做延迟加载,实现还是调用了doExport()方法
1 | protected synchronized void doExport() { |
省略了一下初始化配置的代码,剩下checkApplication()、checkRegistry()和checkProtocol()方法都是配置项的检查,appendProperties(AbstractConfig config)方法上一篇消费者初始化中也分析过了就是初始化执行传入对象的set方法,这里就都不做过多分析了,重点来看一下doExportUrls()方法
1 | private void doExportUrls() { |
loadRegistries(true)方法上次也分析过了,用于获取注册中心的信息,那么继续跟doExportUrlsFor1Protocol(protocolConfig, registryURLs)方法
1 | private void doExportUrlsFor1Protocol(ProtocolConfig protocolConfig, List<URL> registryURLs) { |
方法比较长,在上面一些不是很重要的部分我标了一些注释,就不深入讲了,重点来看一下下面这段
1 | Invoker<?> invoker = proxyFactory.getInvoker(ref, (Class) interfaceClass, registryURL.addParameterAndEncoded(Constants.EXPORT_KEY, url.toFullString())); |
proxyFactory.getInvoker的具体实现就不重复讲了,直接来看JavassistProxyFactory的getInvoker方法
1 | public <T> Invoker<T> getInvoker(T proxy, Class<T> type, URL url) { |
可以看到这个方法返回的是一个AbstractProxyInvoker的实例,通过它代理传入的type类。到这里就完成了具体服务到Invoker的转化。
然后来看protocol.export(invoker),同样直接来看DubboProtocol类的export方法
1 | public <T> Exporter<T> export(Invoker<T> invoker) throws RpcException { |
这里可以看到返回的exporter其实就是对传入的invoker对象进行了包装。这里有一步需要注意,那就是openServer(url),来看一下
1 | private void openServer(URL url) { |
这里需要通过createServer(url)去创建一个服务
1 | private ExchangeServer createServer(URL url) { |
server实际由Exchangers.bind(url, requestHandler)产生,主要作用是绑定并监听端口,默认由Netty实现。这里调用比较深也不是本篇重点,就不再深入了。
总结
本篇主要讲解了Dubbo生产者服务初始化的流程,简单概括起来就是将通过服务生成代理对象Invoker,并将Invoker包装成Exporter对象对外暴露,同时监听指定端口等待消费者的调用。