This article provides a simple summary of the coding-related changes after the multiple-instance transformation of Dubbo 3.
From only ApplicationModel, new ScopeModel/FrameworkModel/ModuleModel are added to express the hierarchical model of multiple instances. Each ScopeModel instance will create and bind its own important members:
ScopeModel, as the most basic model, can hold and pass in SPI/Bean/URL, etc.
The SPI annotation adds the scope attribute to indicate its belonging scope. The correspondence between ExtensionScope and the hierarchical model:
The new ExtensionDirector is used to implement multi-level SPI management and dependency injection.
The creation process of spi extension through ExtensionDirector is as follows:
The scope of visibility is shown in the diagram below: Upper-level objects can inject SPI/Bean objects of the current and lower levels, while lower-level objects cannot inject SPI/Bean objects of upper levels.
A new ScopeBeanFactory is introduced for internal Bean management, supporting sharing a single instance object across multiple different modules. ScopeBeanFactory also supports scope; the injection rules are the same as for ExtensionDirector. For usage, please refer to: FrameworkStatusReportService, RemoteMetadataServiceImpl, MetadataReportInstance
The original ServiceRepository has been split into three classes, corresponding to three different hierarchical models. FrameworkServiceRepository ServiceRepository ModuleServiceRepository
Register the service interface information ProviderModel/ConsumerModel/ServiceDescriptor in ModuleServiceRepository, while keeping a mapping in FrameworkServiceRepository for looking up the corresponding service interface model based on requests.
Original Method: ApplicationModel provides a series of static methods to obtain shared application instance data
ApplicationModel.getConfigManager()
ApplicationModel.getEnvironment()
ApplicationModel.getServiceRepository()
ApplicationModel.getExecutorRepository()
ApplicationModel.getName()
New Method: Find the ApplicationModel instance first, then use instance methods to obtain data
// Get default instance, compatible with the original single application instance
ApplicationModel.defaultModel().getApplicationEnvironment();
// Get ApplicationModel by Module
moduleModel.getApplicationModel();
// Get ApplicationModel through URL
ScopeModelUtil.getApplicationModel(url.getScopeModel());
// Obtain through Config configuration class
ScopeModelUtil.getApplicationModel(serviceConfig.getScopeModel());
// SPI/Bean can use constructor injection
public ConfigManager(ApplicationModel applicationModel) {
this.applicationModel = applicationModel;
}
// SPI/Bean can inject by implementing ScopeModelAware interface
public class DefaultGovernanceRuleRepositoryImpl implements GovernanceRuleRepository, ScopeModelAware {
private ApplicationModel applicationModel;
@Override
public void setApplicationModel(ApplicationModel applicationModel) {
this.applicationModel = applicationModel;
}
// ...
}
// Enumerate all Applications in FrameworkModel
for (ApplicationModel applicationModel : frameworkModel.getApplicationModels()) {
List<RegistryProtocolListener> listeners = applicationModel.getExtensionLoader(RegistryProtocolListener.class)
.getLoadedExtensionInstances();
if (CollectionUtils.isNotEmpty(listeners)) {
for (RegistryProtocolListener listener : listeners) {
listener.onDestroy();
}
}
}
// Enumerate all FrameworkModels
for (FrameworkModel frameworkModel : FrameworkModel.getAllInstances()) {
destroyProtocols(frameworkModel);
}
Original Method: Obtained through static method ExtensionLoader.getExtensionLoader()
ExtensionLoader.getExtensionLoader(Cluster.class).getExtension(name, wrap);
New Method: Obtain through ScopeModel or ExtensionDirector
applicationModel.getExtensionLoader(Cluster.class).getExtension(name, wrap);
Original Method: Lookup service models in ServiceRepository by uniqueServiceName.
New Method: Pass ScopeModel/ServiceModel through URL. Please refer to RegistryProtocol.
Original Method: Preserve bean instances using static variables.
New Method: Share instances through BeanFactory.
Obtain the Model of a certain level based on ScopeModel, with compatibility handling; when scopeModel parameter is null, it returns the default instance: ScopeModelUtil.getFrameworkMode(scopeModel) ScopeModelUtil.getApplicationMode(scopeModel) ScopeModelUtil.getModuleMode(scopeModel)