单页网站模板wap,建设银行手机版官方网站,怎样制作免费手机网站,哈尔滨网站运营服务商正常在项目中#xff0c;我们都是在Spring环境下使用Dubbo#xff0c;所以我们这里就在Spring的环境下看看Dubbo是如何运作的 入口
在源码下载下来之后#xff0c;有一个dubbo-demo目录#xff0c;里面有一个基于spring注解的子目录dubbo-demo-annotation, 里面有一个生产…正常在项目中我们都是在Spring环境下使用Dubbo所以我们这里就在Spring的环境下看看Dubbo是如何运作的 入口
在源码下载下来之后有一个dubbo-demo目录里面有一个基于spring注解的子目录dubbo-demo-annotation, 里面有一个生产者的demo还有一个消费者的demoProvider下面的Application
public class Application {public static void main(String[] args) throws Exception {AnnotationConfigApplicationContext context new AnnotationConfigApplicationContext(ProviderConfiguration.class);context.start();System.in.read();}/*** 1、EnableDubbo* 2、DubboBootstrapApplicationListener监听容器启动事件然后调用DubboBootstrap的start方法* 1、会导出DubboService* 2、会订阅DubboService* 3、*/ConfigurationEnableDubbo(scanBasePackages org.apache.dubbo.demo.provider)PropertySource(classpath:/spring/dubbo-provider.properties)static class ProviderConfiguration {Beanpublic RegistryConfig registryConfig() {RegistryConfig registryConfig new RegistryConfig();registryConfig.setAddress(zookeeper://127.0.0.1:2181);return registryConfig;}}
}dubbo-provider.properties
Consumer下面的Application
public class Application {/*** In order to make sure multicast registry works, need to specify -Djava.net.preferIPv4Stacktrue before* launch the application*/public static void main(String[] args) {AnnotationConfigApplicationContext context new AnnotationConfigApplicationContext(ConsumerConfiguration.class);context.start();DemoService service context.getBean(demoServiceComponent, DemoServiceComponent.class);String hello service.sayHello(world);System.out.println(result : hello);}ConfigurationEnableDubbo(scanBasePackages org.apache.dubbo.demo.consumer.comp)PropertySource(classpath:/spring/dubbo-consumer.properties)ComponentScan(value {org.apache.dubbo.demo.consumer.comp})static class ConsumerConfiguration {}
}dubbo-consumer.properties Provider#Application PropertySource(“classpath:/spring/dubbo-provider.properties”)
这个注解是Spring注解负责解析配置文件把解析到的文件放到Environment对象中。而Dubbo就是从这个对象里面拿到配置值生成对应的对象比如 dubbo.application.name会生成一个ApplicationConfig比如dubbo.protocal.* 会生成一个ProtocalConfig对象 EnableDubbo(scanBasePackages “org.apache.dubbo.demo.provider”) EnableDubboConfig
完成对Dubbo配置的解析把配置文件里面的内容解析成一个一个配置对象 import一个DubboConfigConfigurationRegistrar public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {/** 此方法主要作用* 会对Properties文件进行解析主要完成的事情是根据Properties文件的每个配置项的前缀、参数名、参数值生成对应的Bean。* 比如前缀为dubbo.application的配置项会生成一个 ApplicationConfig 类型的BeanDefinition。* 比如前缀为dubbo.protocol的配置项会生成一个 ProtocolConfig 类型的BeanDefinition。** 都有哪些配置类 具体看* 1、DubboConfigConfiguration.Single* 2、DubboConfigConfiguration.Multiple*/AnnotationAttributes attributes AnnotationAttributes.fromMap(importingClassMetadata.getAnnotationAttributes(EnableDubboConfig.class.getName()));boolean multiple attributes.getBoolean(multiple);// Single Config Bindings// todo 在解析DubboConfigConfiguration.Single会注入ConfigurationBeanBindingsRegisterregisterBeans(registry, DubboConfigConfiguration.Single.class);if (multiple) { // Since 2.6.6 https://github.com/apache/dubbo/issues/3193/*** 默认情况下开启了multiple模式multiple模式表示开启多配置模式意思是这样的1、如果没有开启multiple模式那么只支持配置一个dubbo.protocol比如dubbo.protocol.namedubbodubbo.protocol.port20880dubbo.protocol.host0.0.0.02、如果开启了multiple模式那么可以支持多个dubbo.protocol比如dubbo.protocols.p1.namedubbodubbo.protocols.p1.port20880dubbo.protocols.p1.host0.0.0.0dubbo.protocols.p2.namehttpdubbo.protocols.p2.port8082dubbo.protocols.p2.host0.0.0.0*/registerBeans(registry, DubboConfigConfiguration.Multiple.class);}// Since 2.7.6 todo 看这里registerCommonBeans(registry);}总结一下做了几件事
先往Spring容器注册了一个DubboConfigConfiguration.Single.class, 导致上面有注解引入了EnableConfigurationBeanBindings 在EnableConfigurationBeanBindings上面import了ConfigurationBeanBindingsRegister, 又是相似的套路ConfigurationBeanBindingsRegister也实现了ImportBeanDefinitionRegistrar接口所以也会在Spring启动的时候调用到我们能看到它做了做了几步
从EnableConfigurationBeanBindings 中获取注解的值然后在获取value的属性值value对应的是EnableConfigurationBeanBinding 中的值 创建一个ConfigurationBeanBindingRegistrar类将environment设置到里面然后调用registerConfigurationBeanDefinitions方法
registerConfigurationBeanDefinition这里做了这样几件事1、从注解中获取prefix如果里面有占位符需要从environment中获取、type返回是一个class值比如ApplicationConfig、multiple2、registerConfigurationBeans - PropertySourcesUtils.getSubProperties从配置文件中取出对应的配置3、registerConfigurationBeans - registerConfigurationBean将对应的Config比如ApplicationConfig注册到spring容器中4、registerConfigurationBindingBeanPostProcessor(registry)注册了一个ConfigurationBeanBindingPostProcessor, 为什么需要这个类因为目前我们只是把配置类做成BD放到Spring容器中但是我们并没有赋值所以需要在这个后置处理器中给这些BD赋值
如果开启了multiple, 会往spring中注册一个DubboConfigConfiguration.Multiple.class调用registerCommonBeans, 往Spring容器中配置很多Dubbo需要的Bean比如ReferenceAnnotationBeanPostProcessor处理dubbo_reference注解的、DubboApplicationListenerRegistrar用来创建很多的Listener在spring启动过程中dubbo需要做的一些事等 总结一下DubboConfigConfigurationRegistrar做的事
往Spring容器中放一个DubboConfigConfiguration.Single类
Single就是一个配置模版类上面会有EnableConfigurationBeanBindings这个类又会注入一个类ConfigurationBeanBindingsRegister这个类实现了ImportBeanDefinitionRegistrar 会在Spring启动的时候调用到它的registerBeanDefinitions这个方法最终完成了将Single上面这些个配置转换成XXXConfig 同时还注册了一个ConfigurationBeanBindingPostProcessor完成从配置文件读取这一个个配置并放到XXXConfig中
如果配置的multipletrue就会多走一套multiple配置逻辑核心逻辑和Single其实差不错registerCommonBeans注册了很多Dubbo中用到的通用bean DubboComponentScan
这里同样引入了一个DubboComponentScanRegistrar也就是在spring启动的过程中会调用到它的registerBeanDefinitions方法getPackagesToScan: 返回一个需要扫描的路径集合 registerServiceAnnotationBeanPostProcessor(packagesToScan, registry): 又往spring容器中注册了一个ServiceAnnotationBeanPostProcessor类通过传入了刚刚获取的需要扫描的路径集合 ServiceAnnotationBeanPostProcessor
ServiceAnnotationBeanPostProcessor继承的是ServcieClassPostProcessor这里做了几件事
注册DubboBootstrapApplicationListener到spring容器中这个listener负责监听ContextRefreshedEvent事件如果packagesToScan中有占位符替换掉然后使用registerServiceBeans, 将DubboServcie扫描到Spring容器中 ServiceClassPostProcessor.registerServiceBeans(packagesToScan, BeanDefinitionRegistry registry)
总结一下
创建了一个DubboClassPathBeanDefinitionScanner专门用来扫指定路径包下面的beanDefinition的给scanner设置了IncludeFilter就是我只扫DubboService、Service这些注解的遍历路径包然后使用scanner.scan来看路径包下面有DubboService、Service的beanDefinition将扫到的BeanDefinition然后调用registerServiceBean 将这些spring的bean处理成Dubbo自己的bean ServiceClassPostProcessor.registerServiceBean() Consumer#Application Consumer的大体逻辑和Provider一样肯定也有读取配置的地方最重要的地方就是DubboReference是如何解析的
入口
EnableDubboConfig - Import(DubboConfigConfigurationRegistrar.class) -DubboConfigConfigurationRegistrar.registerBeanDefinitions -registerCommonBeans(registry); ReferenceAnnotationBeanPostProcessor
这个类其实挺有意思的它继承了AbstractAnnotationBeanPostProcessor这个AbstractAnnotationBeanPostProcessor又继承了InstantiationAwareBeanPostProcessorAdapter我们来看一下它的实现类有哪些是不是非常的熟悉AutoWiredAnnotationBeanPostProcessor其实ReferencService和AutoWired的实现原理是一样的都是在Spring依赖注入的时候需要做属性的注入最终会调用到ReferenceAnnotationBeanPostProcessor.doGetInjectedBean ReferenceAnnotationBeanPostProcessor.doGetInjectedBean
一共做了几件事
buildReferencedBeanName
使用buildReferencedBeanName方法得到一个bean的名字这个bean是需要引入服务的beanName最终生成的格式为ServiceBean:org.apache.dubbo.demo.DemoService如果说设置了group或者version都会拼接上去最终生成的格式为ServiceBeaninterfaceClassNameversiongroup
getReferenceBeanName
getReferencBeanName得到的referenceBeanName是我引入时产生的服务名而referencedBeanName对应的serviceBean的服务名称从generateReferenceBeanName我们看的出来referenceBeanName产生规则为Reference注解所有属性的值进行拼接所以就是Reference引入的接口是同一个但注解的值不一样的话这个名字也是不一样的。那么这个名字有什么用他的作用是放到缓存中作为key
buildReferenceBeanIfAbsent 代码主要就是判断缓存中是否存在如果不存在就进行创建流程这里比较复杂我们关系最终得到的referenceBean:
isLocalServiceBean
判断是否是本地服务
registerReferenceBean