官方图
image.png源码分析
public class Provider {
public static void main(String[] args) throws IOException {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(
new String[]{"classpath:spring/dubbo-provider.xml"});
context.start();
System.in.read(); // 按任意键退出
}
}
当项目启动时,ClassPathXmlApplicationContext加载provider.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:dubbo="http://dubbo.apache.org/schema/dubbo"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://dubbo.apache.org/schema/dubbo http://dubbo.apache.org/schema/dubbo/dubbo.xsd">
<dubbo:application name="hello-world-app"/>
<dubbo:registry file="/Users/lemo-wu/output/dubbo.cache" protocol="zookeeper" address="localhost:2181?client=curator"/>
<dubbo:protocol name="dubbo" port="20880"/>
<dubbo:service group="test" version="1.0" interface="com.leimo.demo.DemoService" ref="demoService" timeout="100">
<dubbo:method name="methodTimeout" timeout="1000"/>
</dubbo:service>
<bean id="demoService" class="com.leimo.demo.impl.DemoServiceImpl"/>
</beans>
dubbo:*是自定义命名空间,解析就交给DubboNamespaceHandler
处理,当解析dubbo命名空间下的节点时会触发parse方法
@Override
public BeanDefinition parse(Element element, ParserContext parserContext) {
...
registerApplicationListeners(registry);
...
}
registerApplicationListeners会注册DubboBootstrapApplicationListener监听器
private void registerApplicationListeners(BeanDefinitionRegistry registry) {
...
registerBeans(registry, DubboBootstrapApplicationListener.class);
}
DubboBootstrapApplicationListener监听器是在spring启动,关闭成功后触发的监听器,DubboBootstrapApplicationListener继承OneTimeExecutionApplicationContextEventListener抽象监听器类,根据名字可以知道此监听器只会触发一次
public class DubboBootstrapApplicationListener extends OneTimeExecutionApplicationContextEventListener
implements Ordered {
public static final String BEAN_NAME = "dubboBootstrapApplicationListener";
private final DubboBootstrap dubboBootstrap;
public DubboBootstrapApplicationListener() {
this.dubboBootstrap = DubboBootstrap.getInstance();
}
@Override
public void onApplicationContextEvent(ApplicationContextEvent event) {
if (event instanceof ContextRefreshedEvent) {
onContextRefreshedEvent((ContextRefreshedEvent) event);
} else if (event instanceof ContextClosedEvent) {
onContextClosedEvent((ContextClosedEvent) event);
}
}
private void onContextRefreshedEvent(ContextRefreshedEvent event) {
dubboBootstrap.start();
}
private void onContextClosedEvent(ContextClosedEvent event) {
dubboBootstrap.stop();
}
...
}
DubboBootstrapApplicationListener会在启动时调用DubboBootstrap
的start
方法启动dubbo.
public DubboBootstrap start() {
...
// 1. export Dubbo Services
exportServices();
...
我们只看下exportServices
方法,其他无关代码忽略掉
private void exportServices() {
//configManager.getServices() 获取的就是在provider.xml中配置的dubbo:service对应bean,类型是ServiceConfig
configManager.getServices().forEach(sc -> {
// TODO, compatible with ServiceConfig.export()
ServiceConfig serviceConfig = (ServiceConfig) sc;
serviceConfig.setBootstrap(this);
if (exportAsync) { // 如果exportAsync为true就异步export,否则同步发布,默认为false
ExecutorService executor = executorRepository.getServiceExporterExecutor();
Future<?> future = executor.submit(() -> {
sc.export();
exportedServices.add(sc);
});
asyncExportingFutures.add(future);
} else {
sc.export();
exportedServices.add(sc);
}
});
}
exportAsync
为false,所以走else分支,调用ServiceConfig
的export
方法
后续调用流程export
-> doExport
-> doExportUrls
->doExportUrlsFor1Protocol
private void doExportUrlsFor1Protocol(ProtocolConfig protocolConfig, List<URL> registryURLs) {
Invoker<?> invoker = PROXY_FACTORY.getInvoker(ref, (Class) interfaceClass,
registryURL.addParameterAndEncoded(EXPORT_KEY, url.toFullString()));
DelegateProviderMetaDataInvoker wrapperInvoker = new DelegateProviderMetaDataInvoker(invoker, this);
Exporter<?> exporter = PROTOCOL.export(wrapperInvoker);
exporters.add(exporter);
}
PROXY_FACTORY
默认使用的是JavassistProxyFactory
,通过JavassistProxyFactory
获取Invoker
对象,并最终通过PROTOCOL
export
出去, 值得一提的是PROXY_FACTORY, PROTOCOL使用的是SPI
技术
网友评论