如何从源码分析Dubbo与SpringBoot整合以及进行Dubbo启动,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。
在分析Reference是提到过Dubbo会自动引配置类,这里需要注意DubboBootstrapApplicationListener:
registerCommonBeans(BeanDefinitionRegistry registry) {
registerInfrastructureBean(registry, ReferenceAnnotationBeanPostProcessor.BEAN_NAME,
ReferenceAnnotationBeanPostProcessor.class);
registerInfrastructureBean(registry, DubboConfigAliasPostProcessor.BEAN_NAME,
DubboConfigAliasPostProcessor.class);
registerInfrastructureBean(registry, DubboLifecycleComponentApplicationListener.BEAN_NAME,
DubboLifecycleComponentApplicationListener.class);
registerInfrastructureBean(registry, DubboBootstrapApplicationListener.BEAN_NAME,
DubboBootstrapApplicationListener.class);
registerInfrastructureBean(registry, DubboConfigDefaultPropertyValueBeanPostProcessor.BEAN_NAME,
DubboConfigDefaultPropertyValueBeanPostProcessor.class);
}
public class DubboBootstrapApplicationListener extends OneTimeExecutionApplicationContextEventListener
implements Ordered {
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 实现了Spring的事件监听,当上下文刷新完成的时候,会执行dubboBootstrap.start():
public DubboBootstrap start() {
//CAS
if (started.compareAndSet(false, true)) {
ready.set(false);
//初始化
initialize();
//Dubbo服务导出
exportServices();
if (!isOnlyRegisterProvider() || hasExportedServices()) {
exportMetadataService();
registerServiceInstance();
}
//服务引用
referServices();
}
return this;
}
先看exportServices()服务导出:
private void exportServices() {
configManager.getServices().forEach(sc -> {
ServiceConfig serviceConfig = (ServiceConfig) sc;
serviceConfig.setBootstrap(this);
if (exportAsync) {
ExecutorService executor = executorRepository.getServiceExporterExecutor();
Future<?> future = executor.submit(() -> {
sc.export();
exportedServices.add(sc);
});
asyncExportingFutures.add(future);
} else {
sc.export();
exportedServices.add(sc);
}
});
}
循环configManager.getServices()中的数据依次执行导出,那这些Service是从哪来的?:
public Collection<ServiceConfigBase> getServices() {
return getConfigs(getTagName(ServiceConfigBase.class));
}
最终实际调用:
protected <C extends AbstractConfig> Map<String, C> getConfigsMap(String configType) {
return (Map<String, C>) read(() -> configsCache.getOrDefault(configType, emptyMap()));
}
getTagName(ServiceConfigBase.class) 获取类的标签,这里也就是service。我们之前分析过Dubbo的DubboService注解在注册原始类的同时还会注册ServiceBean。下面看ServiceBean的类结构图, 它是ServiceConfigBase的一个子类,那么他是如何放到configsCache中去的?
再来看ServiceConfigBase的父类AbstractConfig,它里面有一个PostConstruct注解的方法,查看官方解释:PostConstruct注解用于需要依赖注入完成以执行任何初始化之后要执行的方法上。必须在类投入使用之前调用此方法。所有支持依赖注入的类都必须支持该注释。即使该类不要求注入任何资源,也必须调用用PostConstruct注释的方法。也就是说所有的ServiceBean在被Spring初始化之后都会调用addIntoConfigManager方法。
@PostConstruct
public void addIntoConfigManager() {
ApplicationModel.getConfigManager().addConfig(this);
}
addIntoConfigManager方法的实际作用就是向configsCache中缓存:
protected void addConfig(AbstractConfig config, boolean unique) {
if (config == null) {
return;
}
write(() -> {
Map<String, AbstractConfig> configsMap = configsCache.computeIfAbsent(getTagName(config.getClass()), type -> newMap());
addIfAbsent(config, configsMap, unique);
});
}
所以,Dubbo中凡是实现AbstractConfig接口的类,在被Spring初始化之后,最终都会被缓存到configManager中。
总结:
1、Dubbo中实现AbstractConfig接口的Bean,在被Spring初始化之后,都会被放入configManager。
2、Dubbo通过实现Spring的监听事件,在上下文刷新完成的时候开始进行Dubbo服务的初始化和启动。
3、启动引导类dubboBootstrap 是一个单例。
至此,Dubbo容器的启动分析完成。
关于如何从源码分析Dubbo与SpringBoot整合以及进行Dubbo启动问题的解答就分享到这里了,希望以上内容可以对大家有一定的帮助,如果你还有很多疑惑没有解开,可以关注天达云行业资讯频道了解更多相关知识。