先上简易结论:针对一个服务发布是在底层打开socket监听端口(默认netty),接受请求时解析请求参数(请求接口,请求方法,请求参数)去获取接口实现类的动态代理,根据反射调用实现类方法,然后(通过网络)返回请求结果给调用方
dubbo是无缝接入spring的,也因此借着spring的特性去实现一些服务发布需要做的事情(ioc实例化自定义的bean、容器初始化后进行服务发布)
1.服务发布bean的定义、初始化
定义一个服务发布需要在xml(官方推荐用xml配置dubbo)定义下面内容:
<bean id="demoService" class="com.alibaba.dubbo.demo.provider.DemoServiceImpl"/>
<dubbo:service interface="com.alibaba.dubbo.demo.DemoService" ref="demoService"/>
很明显,以上<bean>标签能由spring处理后作为一个bean在容器注册,但<dubbo:service>标签是spring不能处理的,所以由dubbo"告诉"spring应该怎么处理
dubbo有个DubboNamespaceHandler类,继承了spring的NamespaceHandlerSupport(命名空间解析),往解析器列表中加入能解析dubbo标签的解析器
public class DubboNamespaceHandler extends NamespaceHandlerSupport {
static {
Version.checkDuplicate(DubboNamespaceHandler.class);
}
@Override
public void init() {
registerBeanDefinitionParser("application", new DubboBeanDefinitionParser(ApplicationConfig.class, true));
registerBeanDefinitionParser("module", new DubboBeanDefinitionParser(ModuleConfig.class, true));
registerBeanDefinitionParser("registry", new DubboBeanDefinitionParser(RegistryConfig.class, true));
registerBeanDefinitionParser("monitor", new DubboBeanDefinitionParser(MonitorConfig.class, true));
registerBeanDefinitionParser("provider", new DubboBeanDefinitionParser(ProviderConfig.class, true));
registerBeanDefinitionParser("consumer", new DubboBeanDefinitionParser(ConsumerConfig.class, true));
registerBeanDefinitionParser("protocol", new DubboBeanDefinitionParser(ProtocolConfig.class, true));
registerBeanDefinitionParser("service", new DubboBeanDefinitionParser(ServiceBean.class, true));
registerBeanDefinitionParser("reference", new DubboBeanDefinitionParser(ReferenceBean.class, false));
registerBeanDefinitionParser("annotation", new AnnotationBeanDefinitionParser());
}
}
在初始化方法调用父类NamespaceHandlerSupport方法registerBeanDefinitionParser(),代码如下:
private final Map<String, BeanDefinitionParser> parsers = new HashMap<String, BeanDefinitionParser>();
protected final void registerBeanDefinitionParser(String elementName, BeanDefinitionParser parser) {
this.parsers.put(elementName, parser);
}
所以dubbo往spring解析器列表(parsers)中加入能处理特定命名空间的dubbo标签(service、reference等)的解析器DubboBeanDefinitionParser,这样spring在读取xml解析标签时遇到dubbo的标签就会调用相应的解析器的parse()方法去解析
接下来查看DubboBeanDefinitionParser的构造以及重要的解析方法parse()
public class DubboBeanDefinitionParser implements BeanDefinitionParser {
private final Class<?> beanClass;
private final boolean required;
/**
* beanClass:在DubboNamespaceHandler中传进来的Class,即把标签和Class对应起来,这里例子指的是ServiceBean.class
* <dubbo:service> ---解析为--- ServiceBean
*/
public DubboBeanDefinitionParser(Class<?> beanClass, boolean required) {
this.beanClass = beanClass;
this.required = required;
}
@Override
public BeanDefinition parse(Element element, ParserContext parserContext) {
return parse(element, parserContext, beanClass, required);
}
@SuppressWarnings("unchecked")
private static BeanDefinition parse(Element element, ParserContext parserContext, Class<?> beanClass, boolean required) {
RootBeanDefinition beanDefinition = new RootBeanDefinition();
......
if (ServiceBean.class.equals(beanClass)) {
String className = element.getAttribute("class");
if (className != null && className.length() > 0) {
RootBeanDefinition classDefinition = new RootBeanDefinition();
classDefinition.setBeanClass(ReflectUtils.forName(className));
classDefinition.setLazyInit(false);
parseProperties(element.getChildNodes(), classDefinition);
beanDefinition.getPropertyValues().addPropertyValue("ref", new BeanDefinitionHolder(classDefinition, id + "Impl"));
}
......
//把传进来的标签element里的属性(如id、interface、class等)设置给beanDefinition
//根据beanClass(ServiceBean)获取set方法放进beanDefinition记录着
return beanDefinition;
}
}
上面代码是spring初始化遇到dubbo标签时会执行的代码,这里beanDefinition的定义是记录着需要实例化bean的各种信息,相当于模子,有了模子就可以实例化相应的bean出来,返回的beanDefinition最终会放到spring一个beanDefinitionMap<String, BeanDefinition>中,其中key为xml定义的id
spring容器初始化期间会调用如下的代码:
public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory
implements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable {
@Override
public void preInstantiateSingletons() throws BeansException {
// 实例化非懒加载的单例bean
// 获取beanName列表
List<String> beanNames = new ArrayList<String>(this.beanDefinitionNames);
// 遍历beanName列表调用getBean(beanName)实例化bean
for (String beanName : beanNames) {
RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
......
getBean(beanName)