Welcome to the public number [sharedCode] committed to mainstream middleware source analysis, you can contact me directly
preface
In previous articles, we looked at how Spring interprets the @Service, @Reference annotation. Today we’ll focus on a very important class for the Service exposed, ServiceBean, which generates a ServiceBean for every exposed Service.
ServiceBean
The inheritance implementation relationship for this class is as follows
public class ServiceBean<T> extends ServiceConfig<T> implements InitializingBean.DisposableBean.ApplicationContextAware.ApplicationListener<ContextRefreshedEvent>, BeanNameAware {
// code omitted
}
Copy the code
It inherits ServiceConfig, and this class is particularly important, and I’ll talk about it later, because service exposure, SPI mechanisms, are associated with this class
InitializingBean mainly uses its afterPropertiesSet method, which is called after the object has been instantiated to initialize some values
DisposableBean, primarily using its destroy() method, called at Spring container Showdown.
ApplicationContextAware, in order to get applicationContext
ApplicationListener, which adds a context refresh listener to expose service usage.
BeanNameAware, which sets the name of the Bean
setApplicationContext
@Override
public void setApplicationContext(ApplicationContext applicationContext) {
this.applicationContext = applicationContext;
// Set applicationContext to SpringExtensionFactory for subsequent Bean retrieval from SpringExtensionFactory
//SpringExtensionFactory is a dubbo custom class
SpringExtensionFactory.addApplicationContext(applicationContext);
if(applicationContext ! =null) {
SPRING_CONTEXT = applicationContext;
try {
Method method = applicationContext.getClass().getMethod("addApplicationListener".newClass<? >[]{ApplicationListener.class});/ / compatible Spring2.0.1
AddApplicationListener (ApplicationListener
listener),
// Then add the current class (because it listens for ContextRefreshedEvent events) to spring's listener list
method.invoke(applicationContext, new Object[]{this});
supportedApplicationListener = true;
} catch (Throwable t) {
if (applicationContext instanceof AbstractApplicationContext) {
try {
Method method = AbstractApplicationContext.class.getDeclaredMethod("addListener".newClass<? >[]{ApplicationListener.class});/ / compatible Spring2.0.1
if(! method.isAccessible()) { method.setAccessible(true);
}
method.invoke(applicationContext, new Object[]{this});
supportedApplicationListener = true;
} catch (Throwable t2) {
}
}
}
}
}
Copy the code
SpringExtensionFactory is used for dependency injection in Dubbo’s SPI mechanism. When an extension class needs to inject another bean, You might fetch the Bean object from the SpringExtensionFactory class through the applicationContext.
onApplicationEvent
@Override
public void onApplicationEvent(ContextRefreshedEvent event) {
// The service is not lazily loaded && the service is not published && the service is not offline. Service exposure occurs when these three conditions are met
if(isDelay() && ! isExported() && ! isUnexported()) {if (logger.isInfoEnabled()) {
logger.info("The service ready on spring started. service: " + getInterface());
}
// Expose the service interfaceexport(); }}private boolean isDelay(a) {
// Get lazy loading Settings, delay registering service time (ms)-, set to -1, delay exposing service until Spring container initialization is complete
Integer delay = getDelay();
ProviderConfig provider = getProvider();
if (delay == null&& provider ! =null) {
delay = provider.getDelay();
}
// Add context refresh listener, and do not set lazy loading,
return supportedApplicationListener && (delay == null || delay == -1);
}
Copy the code
The above export method is more important and is used for service exposure, which will be discussed separately later.
afterPropertiesSet
Dubbo calls back to the class that implements the InitializingBean when Spring instantiates the bean (initializeBean). The callback method is this method
@Override
@SuppressWarnings({"unchecked", "deprecation"})
public void afterPropertiesSet(a) throws Exception {
//
if (getProvider() == null) {
Map<String, ProviderConfig> providerConfigMap = applicationContext == null ? null : BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, ProviderConfig.class, false.false);
if(providerConfigMap ! =null && providerConfigMap.size() > 0) {
Map<String, ProtocolConfig> protocolConfigMap = applicationContext == null ? null : BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, ProtocolConfig.class, false.false);
if ((protocolConfigMap == null || protocolConfigMap.size() == 0)
&& providerConfigMap.size() > 1) { // backward compatibility
List<ProviderConfig> providerConfigs = new ArrayList<ProviderConfig>();
for (ProviderConfig config : providerConfigMap.values()) {
if(config.isDefault() ! =null&& config.isDefault().booleanValue()) { providerConfigs.add(config); }}if (!providerConfigs.isEmpty()) {
setProviders(providerConfigs);
}
} else {
ProviderConfig providerConfig = null;
for (ProviderConfig config : providerConfigMap.values()) {
if (config.isDefault() == null || config.isDefault().booleanValue()) {
if(providerConfig ! =null) {
throw new IllegalStateException("Duplicate provider configs: " + providerConfig + " and "+ config); } providerConfig = config; }}if(providerConfig ! =null) { setProvider(providerConfig); }}}}// If the current ServiceBan application is empty, set application for the Service
if (getApplication() == null
&& (getProvider() == null || getProvider().getApplication() == null)) {
Map<String, ApplicationConfig> applicationConfigMap = applicationContext == null ? null : BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, ApplicationConfig.class, false.false);
if(applicationConfigMap ! =null && applicationConfigMap.size() > 0) {
ApplicationConfig applicationConfig = null;
for (ApplicationConfig config : applicationConfigMap.values()) {
if (config.isDefault() == null || config.isDefault().booleanValue()) {
if(applicationConfig ! =null) {
throw new IllegalStateException("Duplicate application configs: " + applicationConfig + " and "+ config); } applicationConfig = config; }}if(applicationConfig ! =null) { setApplication(applicationConfig); }}}// If the current module of ServiceBan is empty, set the module for the Service
if (getModule() == null
&& (getProvider() == null || getProvider().getModule() == null)) {
Map<String, ModuleConfig> moduleConfigMap = applicationContext == null ? null : BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, ModuleConfig.class, false.false);
if(moduleConfigMap ! =null && moduleConfigMap.size() > 0) {
ModuleConfig moduleConfig = null;
for (ModuleConfig config : moduleConfigMap.values()) {
if (config.isDefault() == null || config.isDefault().booleanValue()) {
if(moduleConfig ! =null) {
throw new IllegalStateException("Duplicate module configs: " + moduleConfig + " and "+ config); } moduleConfig = config; }}if(moduleConfig ! =null) { setModule(moduleConfig); }}}// If the current ServiceBan Registries is empty, set Registries for the Service
if ((getRegistries() == null || getRegistries().isEmpty())
&& (getProvider() == null || getProvider().getRegistries() == null || getProvider().getRegistries().isEmpty())
&& (getApplication() == null || getApplication().getRegistries() == null || getApplication().getRegistries().isEmpty())) {
Map<String, RegistryConfig> registryConfigMap = applicationContext == null ? null : BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, RegistryConfig.class, false.false);
if(registryConfigMap ! =null && registryConfigMap.size() > 0) {
List<RegistryConfig> registryConfigs = new ArrayList<RegistryConfig>();
for (RegistryConfig config : registryConfigMap.values()) {
if (config.isDefault() == null|| config.isDefault().booleanValue()) { registryConfigs.add(config); }}if(registryConfigs ! =null && !registryConfigs.isEmpty()) {
super.setRegistries(registryConfigs); }}}// If the current ServiceBan Monitor is empty, set the Monitor for the Service
if (getMonitor() == null
&& (getProvider() == null || getProvider().getMonitor() == null)
&& (getApplication() == null || getApplication().getMonitor() == null)) {
Map<String, MonitorConfig> monitorConfigMap = applicationContext == null ? null : BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, MonitorConfig.class, false.false);
if(monitorConfigMap ! =null && monitorConfigMap.size() > 0) {
MonitorConfig monitorConfig = null;
for (MonitorConfig config : monitorConfigMap.values()) {
if (config.isDefault() == null || config.isDefault().booleanValue()) {
if(monitorConfig ! =null) {
throw new IllegalStateException("Duplicate monitor configs: " + monitorConfig + " and "+ config); } monitorConfig = config; }}if(monitorConfig ! =null) { setMonitor(monitorConfig); }}}// If the current Protocol of ServiceBan is empty, set Protocol for the Service
if ((getProtocols() == null || getProtocols().isEmpty())
&& (getProvider() == null || getProvider().getProtocols() == null || getProvider().getProtocols().isEmpty())) {
Map<String, ProtocolConfig> protocolConfigMap = applicationContext == null ? null : BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, ProtocolConfig.class, false.false);
if(protocolConfigMap ! =null && protocolConfigMap.size() > 0) {
List<ProtocolConfig> protocolConfigs = new ArrayList<ProtocolConfig>();
for (ProtocolConfig config : protocolConfigMap.values()) {
if (config.isDefault() == null|| config.isDefault().booleanValue()) { protocolConfigs.add(config); }}if(protocolConfigs ! =null && !protocolConfigs.isEmpty()) {
super.setProtocols(protocolConfigs); }}}// Set the service name
if (getPath() == null || getPath().length() == 0) {
if(beanName ! =null && beanName.length() > 0&& getInterface() ! =null && getInterface().length() > 0&& beanName.startsWith(getInterface())) { setPath(beanName); }}if (!isDelay()) {
export();
}
}
Copy the code
Check to see if any of the ServiceBean properties (here are six) is empty, if so, get the bean of the appropriate type from applicationContext, and if so, set it accordingly.
- ProviderConfig Provider: Indicates whether dubbo:provider is configured
- ApplicationConfig Application: Whether dubbo:application is configured
- ModuleConfig Module: Whether dubbo:module is configured
- List registries: Whether dubbo:registry is configured
- MonitorConfig Monitor: Indicates whether dubbo: indicates monitor is configured
- List protocols: Whether dubbo:protocol is configured
- String path: indicates the service name
That’s how you prepare for Service exposure.
Welcome to the public number [sharedCode] committed to mainstream middleware source analysis, you can contact me directly