我们知道Dubbo有服务提供者和服务消费者,那么今天我们来看服务提供者处的源码,每一个服务都需要注册到注册中心中,这样服务消费者才能看见,并且使用它。
那么服务需要暴露出去,肯定会有一些前期处理,比如服务的属性封装等等。那么今天就来看下主角ServiceBean。
1.服务提供者配置示例如下
<dubbo:application name="${dubbo.application.name}"/>
<dubbo:registry address="${dubbo.registry.address}" timeout="${dubbo.registry.timeout}"
check="${dubbo.registry.check}"/>
<dubbo:protocol name="${dubbo.protocol.name}" port="${dubbo.protocol.port}"/>
<dubbo:provider loadbalance="${dubbo.provider.loadbalance}" retries="${dubbo.provider.retries}"
timeout="${dubbo.provider.timeout}"/>
<dubbo:service interface="com.test.IDubboTestService" ref="dubboTestService"/>
2.那么对于IDubboTestService这个service,Spring会通过解析得到它的Bean,针对每一个Service,都会有一个ServiceBean。
1.ServiceConfig:服务具体的暴露过程由它来进行。
2.ApplicationContextAware:不用多说了吧,Spring里获取容器的类。
3.ApplicationListener:Spring容器内事件的监听,Dubbo内主要使用的是刷新事件。
4.InitializingBean:Bean属性构建好之后的处理过程,方法为afterPropertiesSet。
3.下面分块进行源码的赏析~~~
3.1 ApplicationContextAware的方法setApplicationContext()。在此不去扩展Spring内的知识,知道一下这个方法是干什么的即可。当Srping初始化完成这个Bean之后,会调用setApplicationContext()注入到该Bean中。
3.1.1 Dubbo中主要是将ApplicationContext注入到SpringExtensionFactory中,至于为什么是SpringExtensionFactory,这里涉及到SPI的知识,后续去学习SPI的时候来思考。
3.1.2 获取addApplicationListener,然后将当前Bean将入到监听列表中,此处的作用是后续需要发布该Bean。
private static final long serialVersionUID = 213195494150089726L;
private static transient ApplicationContext SPRING_CONTEXT;
private transient ApplicationContext applicationContext;
private transient String beanName;
private transient boolean supportedApplicationListener;
public ServiceBean() {
super();
}
public ServiceBean(Service service) {
super(service);
}
public static ApplicationContext getSpringContext() {
return SPRING_CONTEXT;
}
public void setApplicationContext(ApplicationContext applicationContext) {
this.applicationContext = applicationContext;
SpringExtensionFactory.addApplicationContext(applicationContext);
if (applicationContext != null) {
SPRING_CONTEXT = applicationContext;
try {
Method method = applicationContext.getClass().getMethod("addApplicationListener", new Class<?>[]{ApplicationListener.class}); // 兼容Spring2.0.1
method.invoke(applicationContext, new Object[] {this});
supportedApplicationListener = true;
} catch (Throwable t) {
if (applicationContext instanceof AbstractApplicationContext) {
try {
Method method = AbstractApplicationContext.class.getDeclaredMethod("addListener", new Class<?>[]{ApplicationListener.class}); // 兼容Spring2.0.1
if (! method.isAccessible()) {
method.setAccessible(true);
}
method.invoke(applicationContext, new Object[] {this});
supportedApplicationListener = true;
} catch (Throwable t2) {
}
}
}
}
}
3.2 InitializingBean,属性构建完毕之后执行。主要获取的东西如下:(都是一些配置值,发布服务所用)
3.2.1 ProviderConfig
3.2.2 ApplicationConfig
3.2.3 ModuleConfig
3.2.4 List<RegistryConfig>
3.2.5 MonitorConfig
3.2.6 List<ProtocolConfig>
3.2.7 path(服务名称)
public void afterPropertiesSet() 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) { // 兼容旧版本
List<ProviderConfig> providerConfigs = new ArrayList<ProviderConfig>();
for (ProviderConfig config : providerConfigMap.values()) {
if (config.isDefault() != null && config.isDefault().booleanValue()) {
providerConfigs.add(config);
}
}
if (providerConfigs.size() > 0) {
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 (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 (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 ((getRegistries() == null || getRegistries().size() == 0)
&& (getProvider() == null || getProvider().getRegistries() == null || getProvider().getRegistries().size() == 0)
&& (getApplication() == null || getApplication().getRegistries() == null || getApplication().getRegistries().size() == 0)) {
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.size() > 0) {
super.setRegistries(registryConfigs);
}
}
}
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 ((getProtocols() == null || getProtocols().size() == 0)
&& (getProvider() == null || getProvider().getProtocols() == null || getProvider().getProtocols().size() == 0)) {
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.size() > 0) {
super.setProtocols(protocolConfigs);
}
}
}
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();
}
}
3.3 delay()方法主要是看provider内是不是提供了这个配置。
private boolean isDelay() {
Integer delay = getDelay();
ProviderConfig provider = getProvider();
if (delay == null && provider != null) {
delay = provider.getDelay();
}
return supportedApplicationListener && (delay == null || delay.intValue() == -1);
}
3.4 ApplicationListener接口内的onApplicationEvent()方法。每当在一个ApplicationEvent发布到 ApplicationContext时,这个bean得到通知就会执行这个方法。是一个标准的Observer设计模式。
暴露条件:delay没有设置或者是-1 && 服务没有暴露 && 服务没有反注册(不太懂这个),那么进行暴露。
public void onApplicationEvent(ApplicationEvent event) {
if (ContextRefreshedEvent.class.getName().equals(event.getClass().getName())) {
if (isDelay() && ! isExported() && ! isUnexported()) {
if (logger.isInfoEnabled()) {
logger.info("The service ready on spring started. service: " + getInterface());
}
export();
}
}
}
3.5 源码小结一下:
总的来说,比较重要的就是onApplicationEvent和afterPropertiesSet,这边需要说一下afterPropertiesSet内的一处代码如下:
在此处其实已经有了是否发布的判断了,如果延迟的时间大于0,那么在此处就会进行暴露export(),如果不是,结束。真正的暴露会在容器发生上下文刷新时进行。
public void afterPropertiesSet() throws Exception {
//....
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();
}
}
3.6另外还需注意的是 父类ServiceConfig中存在两个静态变量,如下:我们知道,当初始化一个类时,如果存在父类,则会先进行父类的初始化操作。这个本篇先不去关注,后续篇幅去理解。
private static final Protocol protocol = ExtensionLoader.getExtensionLoader(Protocol.class).getAdaptiveExtension();
private static final ProxyFactory proxyFactory = ExtensionLoader.getExtensionLoader(ProxyFactory.class).getAdaptiveExtension();
至此,一个ServiceBean已经准备好了,就等着上下文刷新时去暴露export()。