几个重要的类
-
DubboNamespaceHandler
。该类继承NamespaceHandlerSupport
,即通过spring对扩展标签的支持,对dubbo自定义的标签进行解析,在解析时会注册DubboBootstrapApplicationListener
。 -
DubboBootstrapApplicationListener
。该类实现了ApplicationListener
和ApplicationContextAware
,注入ApplicatonContext
并且监听ApplicationContext
的onContextRefreshedEvent
和onContextClosedEvent
事件,在onContextRefresh
时调用DubboBootstrap.start();
开启dubbo。 -
DubboBootstrap
。dubbo
的启动类,start
方法中调用export
方法进行服务提供端的服务暴露,内部会调用ServiceConfig
的export
来暴露服务。 -
ServiceConfig
,主要是对提供者方法的暴露,主要逻辑在doExport
方法内。默认是先将ServiceImpl包装成一个代理对象AbstractProxyInvoker
,该过程是通过某个代理工厂来操作的,例如JdkProxyFactory
或者JavassistProxyFactory
,默认是后者。包装完成后交给某个协议实现类来将Invoker
转换为Exporter
,默认为DubboProtocol
。 -
DubboProtocol
。该类继承了AbstractProtocol
,间接实现了Protocol
。在export
方法中调用HeaderExchanger
的bind
方法,进而调用transport
的bind
来开启server。该处定义了很多Transport,默认的是使用netty,并且是netty4,即在NettyTransporter
中开启netty server,在netty中添加了dubbo协议解析的部分,主要是使用了DubboCountCodec
,内部调用DubboCodec
进行解析。开启server时注册一个ChannelHandlerAdapter
,通过该ChannelHandler处理Channel并找到Invocation
对应的Exporter
,再通过Exporter
来找到Invoker
,这里的Invoker
就是上面ServiceImp
生成的代理类。 -
DubboCodec
。dubbo协议的详细代码。 -
ServiceClassPostProcessor
。该类实现BeanDefinitionRegistryPostProcessor
,将上面的DubboBootstrapApplicationListener
注册为spring
中的bean
。该类中还添加了对注解的支持,添加扫描包路径可以自动注册要暴露的service
类。
dubbo遵循"微内核+插件"的设计模式,大部分插件都使用了spi的方式。
大多数会使用xml的方式使用dubbo,这时候是通过DubboNamespaceHandler
来对DubboBootstrapApplicationListener
进行bean的注册。如果不使用xml,而是通过JavaConfig的方式,可以手动注册ServiceClassPostProcessor
作为bean,如下所示
provider
@Configuration
public class CustomDubboConfig {
@Bean
public ServiceClassPostProcessor serviceClassPostProcessor(){
return new ServiceClassPostProcessor("com.dubbo.provider.service.impl");
}
@Bean
public ApplicationConfig applicationConfig(){
ApplicationConfig config = new ApplicationConfig("without-xml-provide");// 要扫描的service包
return config;
}
@Bean
public RegistryConfig registryConfig(){
return new RegistryConfig("zookeeper://127.0.0.1:2181");
}
}
Service
通过注解DubboService
进行暴露。
@DubboService
public class DemoServiceImpl implements DemoService {
public String sayHello(String s) {
return "from provider:" + s;
}
}
consumer
配置类
@Configuration
public class CustomDubboConfig {
@Bean
public ServiceClassPostProcessor serviceClassPostProcessor(){
return new ServiceClassPostProcessor();
}
@Bean
public ApplicationConfig applicationConfig(){
ApplicationConfig config = new ApplicationConfig("without-xml-consumer");
return config;
}
@Bean
public RegistryConfig registryConfig(){
return new RegistryConfig("zookeeper://127.0.0.1:2181");
}
@Bean
public ConsumerService consumerService(){
return new ConsumerService((DemoService) referenceConfigs().get(DemoService.class).get());
}
@Bean
public Map<Class,ReferenceConfig> referenceConfigs(){
ReferenceConfig<DemoService> config = new ReferenceConfig<>();
config.setInterface(DemoService.class);
Map<Class,ReferenceConfig> map = new HashMap<>();
map.put(DemoService.class, config);
return map;
}
}
消费者端的service类
public class ConsumerService {
DemoService demoService;
public ConsumerService(DemoService service){
demoService = service;
}
public String hello(){
String result = demoService.sayHello("ace");
return result;
}
}
测试成功
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(CustomDubboConfig.class);
context.start();
ConsumerService service = context.getBean(ConsumerService.class);
System.out.println(service.hello());
System.in.read();
也可以使用DubboReference
为方法或者属性添加注解,如下所示
public class ConsumerService {
@DubboReference(interfaceClass = DemoService.class)
DemoService demoService;
public String hello(){
String result = demoService.sayHello("ace");
return result;
}
}
这时候需要在配置类文件开启Dubbo配置
@Configuration
@EnableDubboConfig
public class CustomDubboConfig {
...
需要注意的是,当前使用的是apache.dubbo
,而不是alibaba.dubbo
,需要高版本的spring
,还要添加org.apache.curator
的依赖。curator
是一个zookeeper client实现。
参考