dubbo-config-spring模块是dubbo-config的Extension。
Dubbo的扩展点加载从JDK标准的SPI(Service Provider Interface)扩展点发现机制加强而来。
Dubbo改进了JDK标准的SPI的以下问题:
JDK标准的SPI会一次性实例化扩展点所有实现,如果有扩展实现初始化很耗时,但如果没用上也加载,会很浪费资源。
如果扩展点加载失败,连扩展点的名称都拿不到了。比如:JDK标准的ScriptEngine,通过getName();获取脚本类型的名称,但如果RubyScriptEngine因为所依赖的jruby.jar不存在,导致RubyScriptEngine类加载失败,这个失败原因被吃掉了,和ruby对应不起来,当用户执行ruby脚本时,会报不支持ruby,而不是真正失败的原因。
增加了对扩展点IoC和AOP的支持,一个扩展点可以直接setter注入其它扩展点。
dubbo的spi约定:在扩展类的jar包内,放置扩展点配置文件:META-INF/dubbo/接口全限定名,内容为:配置名=扩展实现类全限定名,多个实现类用换行符分隔。
@SPI
public interface ExtensionFactory {
/**
* Get extension.
*
* @param type object type.
* @param name object name.
* @return object instance.
*/
<T> T getExtension(Class<T> type, String name);
}
dubbo的扩展点接口ExtensionFactory ,该接口有三个实现
dubbo的扩展实现的具体类是ExtensionLoader。
ExtensionLoader加载扩展点时,会检查扩展点的属性(通过set方法判断),如该属性是扩展点类型,则会注入扩展点对象。因为注入时不能确定使用哪个扩展点(在使用时确定),所以注入的是一个自适应扩展(一个代理)。自适应扩展点调用时,选取一个真正的扩展点,并代理到其上完成调用。Dubbo是根据调用方法参数(上面有调用哪个扩展点的信息)来选取一个真正的扩展点。
@SuppressWarnings("unchecked")
private T createExtension(String name) {
Class<?> clazz = getExtensionClasses().get(name);
if (clazz == null) {
throw findException(name);
}
try {
T instance = (T) EXTENSION_INSTANCES.get(clazz);
if (instance == null) {
EXTENSION_INSTANCES.putIfAbsent(clazz, (T) clazz.newInstance());
instance = (T) EXTENSION_INSTANCES.get(clazz);
}
injectExtension(instance);
Set<Class<?>> wrapperClasses = cachedWrapperClasses;
if (wrapperClasses != null && wrapperClasses.size() > 0) {
for (Class<?> wrapperClass : wrapperClasses) {
instance = injectExtension((T) wrapperClass.getConstructor(type).newInstance(instance));
}
}
return instance;
} catch (Throwable t) {
throw new IllegalStateException("Extension instance(name: " + name + ", class: " +
type + ") could not be instantiated: " + t.getMessage(), t);
}
}
private T injectExtension(T instance) {
try {
if (objectFactory != null) {
for (Method method : instance.getClass().getMethods()) {
if (method.getName().startsWith("set")
&& method.getParameterTypes().length == 1
&& Modifier.isPublic(method.getModifiers())) {
Class<?> pt = method.getParameterTypes()[0];
try {
String property = method.getName().length() > 3 ? method.getName().substring(3, 4).toLowerCase() + method.getName().substring(4) : "";
Object object = objectFactory.getExtension(pt, property);
if (object != null) {
method.invoke(instance, object);
}
} catch (Exception e) {
logger.error("fail to inject via method " + method.getName()
+ " of interface " + type.getName() + ": " + e.getMessage(), e);
}
}
}
}
} catch (Exception e) {
logger.error(e.getMessage(), e);
}
return instance;
}
可以看出ExtensionLoader持有某一类扩展点的所有扩展,并且扩展以class为key,一个扩展类只有一个实例。
如果扩展点使用了Adaptive则会通过字节码生成一个自适应的扩展类。
通过createAdaptiveExtensionClassCode方法返回class的code,然后通过Compiler接口返回class对象
/**
* Compiler. (SPI, Singleton, ThreadSafe)
*
* @author william.liangf
*/
@SPI("javassist")
public interface Compiler {
/**
* Compile java source code.
*
* @param code Java source code
* @param classLoader TODO
* @return Compiled class
*/
Class<?> compile(String code, ClassLoader classLoader);
}
Compiler dubbo支持jdk和Javassist两种实现,特别注意一点,JdkCompiler的java版本通过硬编码指定版本为1.6。
JdkCompiler首先通过JavaFileObject接口生成java文件,然后通过JavaCompiler接口编译成class文件,最后通过ClassLoader加载生成的class文件。
---------------------------分隔线-------------------------
spring名称空间扩展
dubbo通过扩展spring的名称空间来读取xml配置。
dubbo.xsd是spring schma的扩展文件。作用是定义相关xml元素和名称空间。
spring.handlers,spring.schemas是spring在解析xml的时候根据spi机制读取对象的NamespaceHandler和xsd文件位置。
很多程序猿使用dubbo开发的时候,会发现ide工具报错,因为xml上面dubbo名称空间的链接打不开,其实这个报错可以无视的,因为spring解析的xml的时候这个网络地址其实是指向spi配置文件里面的一个java类。
spring.handlers
http\://code.alibabatech.com/schema/dubbo=com.alibaba.dubbo.config.spring.schema.DubboNamespaceHandler
DubboNamespaceHandler则注册了相关自定义元素的解析器
/**
* DubboNamespaceHandler
*
* @author william.liangf
* @export
*/
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));
}
}
- 大小: 94.4 KB
- 大小: 40.1 KB
分享到:
相关推荐
dubbo.xsd 下载 添加 xsd 源码位置获得:dubbo-config\dubbo-config-spring\src\main\resources\META-INF\dubbo.xsd
java系统源码 SpringCloud笔记 1、前言 1.1、回顾 回顾之前的知识 JavaSE 数据库 前端 Servlet Http Mybatis Spring SpringMVC SpringBoot Dubbo、Zookeeper、分布式基础 Maven、Git Ajax、Json ... 串一下自己会的...
incubator-dubbo-spring-boot-project apache的dubbo-springboot项目 Spring-Cloud-Admin Spring Cloud微服务化开发平台,具有统一授权、认证后台管理系统,其中包含具备用户管理、资源权限管理、网关API管理等多个...
课程中对比了 Dubbo 和 SpringCloud,并深入讲授SpringCloud核心组件Eureka、Ribbon、Feign、Hystrix、HystrixDashboard、Zuul、Config。除此之外,还通过整合SpringMVC+SpringBoot+Mybatis构建一个可用的基于Spring...
xml java系统源码 DeepEXI Dubbo Scaffold Generator 此脚手架生成器基于构建。...:check_mark_button:Spring-Cloud-Config 消息队列 :check_mark_button:RabbitMQ :check_box_with_check:RocketMQ Kafka 注册中心
SpringMVC | MVC框架 | [http://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/#mvc](http://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/#mvc) ...
基于分布式事务seata+分库分表shardingspherejdbc+nacos+dubbo项目源码.zip 1. 环境准备 - nacos: `sh ./docker/nacos/startup.sh` - seata-server - 导入配置: `sh ./docker/seata-server/conf/nacos-config.sh ...
maven+spring mvc+hibernate+dubbo+velocity+mysql的demo源码,运行前请修改resources/config.properties下的数据配置
maven+spring mvc+hibernate+dubbo+mysql的demo源码,运行前请修改resources/config.properties下的数据配置
课程中对比了 Dubbo 和 SpringCloud,并深入讲授SpringCloud核心组件Eureka、Ribbon、Feign、Hystrix、HystrixDashboard、Zuul、Config。除此之外,还通过整合SpringMVC+SpringBoot+Mybatis构建一个可用的基于Spring...
课程中对比了 Dubbo 和 SpringCloud,并深入讲授SpringCloud核心组件Eureka、Ribbon、Feign、Hystrix、HystrixDashboard、Zuul、Config。除此之外,还通过整合SpringMVC+SpringBoot+Mybatis构建一个可用的基于...
课程中对比了 Dubbo 和 SpringCloud,并深入讲授SpringCloud核心组件Eureka、Ribbon、Feign、Hystrix、HystrixDashboard、Zuul、Config。除此之外,还通过整合SpringMVC+SpringBoot+Mybatis构建一个可用的基于Spring...
12.硅谷学习_SpringCloud_SpringCloud_VS_Dubbo区别对比 13.硅谷学习_SpringCloud_SpringCloud功能域和官网资料介绍 14.硅谷学习_SpringCloud_SpringCloud国内使用情况 15.硅谷学习_SpringCloud_Rest微服务案例-...
12.尚硅谷_SpringCloud_SpringCloud_VS_Dubbo区别对比 13.尚硅谷_SpringCloud_SpringCloud功能域和官网资料介绍 14.尚硅谷_SpringCloud_SpringCloud国内使用情况 15.尚硅谷_SpringCloud_Rest微服务案例-总体概述 ...
循序渐进,学习Spring Boot、Spring Boot & Shiro、Spring Cloud、Spring Security & Spring Security OAuth2,博客Spring系列源码 一、Spring Boot教程 开启Spring Boot Spring Boot基础配置 Spring Boot中使用...
本套源码从面试题,到SpringCloud各种核心组件,到最终的微服务架构总结,帮助...其中中对比了 Dubbo 和 SpringCloud,并深入讲授SpringCloud核心组件Eureka、Ribbon、Feign、Hystrix、HystrixDashboard、Zuul、Config
SpringCloudNetFlix的eureka服务注册/发现、ribbon负载均衡、feign面向接口、zull路由网关(路由拦截、转发)、config配置中心、histrix的服务熔断降级、dishboard。 SpringCloud集成dubbo服务注册发现。 Spring...
文章目录丛林背景角色(一)自定义注解 StrategyBean(二)自定义注解 StrategyBeanScan(三)...例如 Dubbo框架通过这个扩展点将添加了自定义注解@org.apache.dubbo.config.annotation.Service和@org.apache.dubbo
可以看出,所有的相关整合我都是用的一种结构,这种结构其实是可以适用于 Dubbo 和 微服务 架构的,也是出于习惯,即使有些单个的技术点可能只需用到一两个类文件,我也是“不厌其烦”,更或者说是想保持一种统一的...