Dubbo中Bean的加载-1-ServiceBean
来源:互联网 发布:centos6.5编译安装php 编辑:程序博客网 时间:2024/06/06 04:33
摘要
在前面的文章https://goo.gl/d5SR9t中我们介绍过基于Spring的Schema扩展,实际上就是自定义一些XML标签,通过实现Sring的一些接口解析这些标签,然后在Spring容器启动的时候可以自动调用解析过程,生成bean或者做其他操作,Dubbo中bean的生成过程也是依照这样的原理。
dubbo中自定义Schema及解析
Dubbo中自定义的标签及解析过程实现都在dubbo-config-spring这个包中。
Schema配置
下面是META-INF下的sping.handlers和spring.schemas两个文件的内容:
spring.handlers:
http\://code.alibabatech.com/schema/dubbo=com.alibaba.dubbo.config.spring.schema.DubboNamespaceHandler
spring.schemas:
http\://code.alibabatech.com/schema/dubbo/dubbo.xsd=META-INF/dubbo.xsd
schema解析
查看spring.handlers配置中的DubboNamespaceHandler类可以看到如下的代码:
public class DubboNamespaceHandler extends NamespaceHandlerSupport { static { Version.checkDuplicate(DubboNamespaceHandler.class); } 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 DubboBeanDefinitionParser(AnnotationBean.class, true)); }}
这个类继承了NamespaceHandlerSupport,需要实现init方法。
NamespaceHandlerSupport的作用是在自定义标签时对自定义的标签注册相应的解析对象,在Spring容器启动时会自动调用里面的init()方法,从而完成对自定义标签的解析。从上面的代码可以看出,所有的解析代码都是在DubboBeanDefinitionParser中,通过参数控制解析不同的标签。
在实际开发过程中会发现,当我们编写provider的代码时,最常用的是< dubbo:service>标签,编写consumer代码时,最常用的是< dubbo:reference>标签。其中service相关标签主要靠ServiceBean这个类解析,reference相关标签主要一来ReferenceBean类解析。
ServiceBean分析
ServiceBean< T>这个类
(1) 继承了ServiceConfig< T>:这个类主要封装标签的属性,如ref,path,methods等;
(2)实现InitializingBean, DisposableBean接口:
作用:
关于在spring 容器初始化 bean 和销毁前所做的操作定义方式有三种:
第一种:通过@PostConstruct 和 @PreDestroy 方法 实现初始化和销毁bean之前进行的操作
第二种是:通过 在xml中定义init-method 和 destory-method方法
第三种是: 通过bean实现InitializingBean和 DisposableBean接口
(3)实现ApplicationContextAware接口:
实现这个接口需要覆盖setApplicationContext(ApplicationContext applicationContext)方法。
作用:
可以获取ApplicationContext,我们知道,Spring中最重要的就是ApplicationContext了,设置完ApplicationContext后就可以随意使用容器中的bean或者其他的对象了。
(4)实现ApplicationListener接口:
实现这个接口需要覆盖onApplicationEvent(ApplicationEvent event) 这个方法。
作用:
可以监听到所用通过applicationContext.publistEvent(ApplicationEvent event))发布的事件,Spring在启动过程中,对象初始化完成后,会调用publistEvent方法,发布事件,随后所有实现了ApplicationListener的接口都可以接收到事件并执行响应的操作。
具体可以参考:
http://wiki.jikexueyuan.com/project/spring/event-handling-in-spring.html
http://www.cnblogs.com/ArtsCrafts/p/Spring_Event.html
此处是通过监听Spring的内置事件ContextRefreshedEvent调用export()方法暴露服务。
(5)实现BeanNameAware接口:
实现这个接口需要覆盖setBeanName(String name) 方法
作用:
让Bean获取自己在BeanFactory配置中的名字(根据情况是id或者name),适用于某个bean需要访问配置文件中自身bean的id属性的情况。
也就是说在做service标签解析的时候,需要定义的beanName,这个获取到的beanName用在了afterPropertiesSet方法在setPath里面。
具体参考:
http://langgufu.iteye.com/blog/1499966
http://www.cnblogs.com/liunanjava/p/4401089.html
说明:
通过运行dubbo-demo-provider发现,此处给出的beanName是:com.alibaba.dubbo.demo.DemoService。理论上来讲应该是设置的id才对,那么我们看配置文件:
<bean id="demoService" class="com.alibaba.dubbo.demo.provider.DemoServiceImpl" /><dubbo:service interface="com.alibaba.dubbo.demo.DemoService" ref="demoService" />
我们发现这里并没有为< dubbo:service>这个标签指定id或者name属性,那么这个beanName是如何设置进去的呢?
查看解析代码我们可以看到这样的一段:
String id = element.getAttribute("id"); if ((id == null || id.length() == 0) && required) { String generatedBeanName = element.getAttribute("name"); if (generatedBeanName == null || generatedBeanName.length() == 0) { if (ProtocolConfig.class.equals(beanClass)) { generatedBeanName = "dubbo"; } else { generatedBeanName = element.getAttribute("interface"); } } if (generatedBeanName == null || generatedBeanName.length() == 0) { generatedBeanName = beanClass.getName(); } id = generatedBeanName; int counter = 2; while(parserContext.getRegistry().containsBeanDefinition(id)) { id = generatedBeanName + (counter ++); } } if (id != null && id.length() > 0) { if (parserContext.getRegistry().containsBeanDefinition(id)) { throw new IllegalStateException("Duplicate spring bean id " + id); } parserContext.getRegistry().registerBeanDefinition(id, beanDefinition); beanDefinition.getPropertyValues().addPropertyValue("id", id); } ...
到这里就很清楚了,原因是如果没有设置id属性的话,会取interface属性作为SpringBean的id。
其他的内容就是一些设置providerConfig,applicationConfig,moduleConfig,registryConfigs,monitorConfig,protocolConfigs
具体可以参考:
http://chenjingbo.iteye.com/blog/2008325
- Dubbo中Bean的加载-1-ServiceBean
- Dubbo源码分析(四):dubbo中bean的加载
- Dubbo系列(九)Dubbo源码分析之dubbo中bean的加载
- 精通Dubbo——dubbo2.0源码中Spring Bean的加载
- 精通Dubbo——dubbo2.0源码中Spring Bean的加载
- spring中bean的加载1
- dubbo 加载Bean和远程调用分析(1)
- dubbo 加载Bean和远程调用分析(1)
- spring中bean的加载
- Spring3中Bean的加载解析
- Spring中bean的加载过程
- spring bean的加载
- bean的延迟加载
- spring的bean加载
- bean的生命周期加载
- spring源码学习(六)Bean的加载(中)
- dubbo 2标签解析 ServiceBean<T> 生产者服务暴漏过程
- bean的加载(四)从bean的实例中获取对象
- CNN(卷积神经网络)、RNN(循环神经网络)、DNN(深度神经网络)的内部网络结构有什么区别?(知呼回答)
- 技术书籍、GitHub
- 不管你做什么工作,这5项能力必须掌握!
- 加载一个react native 页面
- 各个平台的mysql重启命令
- Dubbo中Bean的加载-1-ServiceBean
- Linux /dev目录详解和Linux系统各个目录的作用
- android 录音播放管理工具
- gradle异常总结
- RSA加密&解密
- Java语言基础使用变量的注意事项
- 枚举enum用法
- PAT A 1118. Birds in Forest
- 在C#中??和?分别是什么意思?