dubbo是基于spring构建和运行的,兼容spring配置。这篇说说dubbo基于spring的过程。 dubbo首先利用了从spring2.0开始的一个特性,Extensible XML authoring,扩展spring了标签功能。 关于如何利用spring扩展自己的标签,可以参考下官方介绍 https://docs.spring.io/spring/docs/3.2.18.RELEASE/spring-framework-reference/htmlsingle/#extensible-xml 根据文档的说法,需要如下4步: 1,编写xml,描述需要扩展的标签的配置属性,dubbo实现放在jar包META-INF/dubbo.xsd文件里 同时通过编写META-INF/spring.handlers文件,提供给spring,内容如下 http://code.alibabatech.com/schema/dubbo/dubbo.xsd=META-INF/dubbo.xsd xsd文件也很好编写阅读,里面有继承和嵌套的概念。 2,写一个NamespaceHandler接口实现类,dubbo的实现类是DubboNamespaceHandler 同时通过编写META-INF/spring.schemas文件,提供给spring,内容如下: http://code.alibabatech.com/schema/dubbo=com.alibaba.dubbo.config.spring.schema.DubboNamespaceHandler 3,编写一个(或者多个)BeanDefinitionParser实现类,用来解析扩展的元素,dubbo实现类是DubboBeanDefinitionParser, 这个类也是真正的需要自己处理的代码所在。 4,把以上组件注册给spirng,这个dubbo其实在DubboNamespaceHandler类里。
DubboNamespaceHandler类实现:
代码语言:javascript复制public class DubboNamespaceHandler extends NamespaceHandlerSupport {
static {
Version.checkDuplicate(DubboNamespaceHandler.class);
}
public void init() {
//设置每个扩展标签对应解析类,并注册扩展的10个标签
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));
}
}
完成以上事情,spring就能识别dubbo的扩展标签了。下面分别从代码层面看看具体实现。
上面提到的10个扩展标签,分别对应10个配置类。类的层次关系:
主要基类是AbstractConfig和AbstractMethodConfig,而AbstractConfig又是所有类的基类。 这10个配置类中ReferenceBean,ServiceBean,AnnotationBean 3个类又都实现了若干spring接口,这3个类算是利用spring完成dubbo调用的驱动类,后面要分别看源码。
DubboBeanDefinitionParser类
这个类实现了BeanDefinitionParser接口,这是个spring的原生接口,里面只有一个方法 public interface BeanDefinitionParser { BeanDefinition parse(Element element, ParserContext parserContext); } 根据接口定义,这个方法实现,需要解析Element元素成原生的BeanDefinition类对象,然后利用 ParserContext对象的getRegistry()返回的注册器来注册解析后BeanDefinition类对象, 最后返回这个BeanDefinition类对象。下面是dubbo的实现,它主要完成spring配置到spring容器内部BeanDefinition转化过程。代码:
代码语言:javascript复制private static BeanDefinition parse(Element element, ParserContext parserContext, Class<?> beanClass, boolean required) {
// new RootBeanDefinition 对象,作为注册和返回的对象
RootBeanDefinition beanDefinition = new RootBeanDefinition();
//设置class
beanDefinition.setBeanClass(beanClass);//
beanDefinition.setLazyInit(false);
String id = element.getAttribute("id");//获取id
if ((id == null || id.length() == 0) && required) {
//无法获取id的按策略生成id
String generatedBeanName = element.getAttribute("name");
if (generatedBeanName == null || generatedBeanName.length() == 0) {
if (ProtocolConfig.class.equals(beanClass)) {
//ProtocolConfig 类型为dubbo开头
generatedBeanName = "dubbo";
} else {
generatedBeanName = element.getAttribute("interface");
}
}
if (generatedBeanName == null || generatedBeanName.length() == 0) {
generatedBeanName = beanClass.getName();
}
id = generatedBeanName;
int counter = 2;
//id 为name1,name2 形式,检测id 是否存在,存在id,序号自增
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()注册beanDefinition
parserContext.getRegistry().registerBeanDefinition(id, beanDefinition);
//这是beanDefinition id属性
beanDefinition.getPropertyValues().addPropertyValue("id", id);
}
//把所有protocol属性name等于id&&类型是ProtocolConfig的
// protocol 属性设置为 new RuntimeBeanReference(id),应用当前BeanDefinition
if (ProtocolConfig.class.equals(beanClass)) {
for (String name : parserContext.getRegistry().getBeanDefinitionNames()) {
BeanDefinition definition = parserContext.getRegistry().getBeanDefinition(name);
PropertyValue property = definition.getPropertyValues().getPropertyValue("protocol");
if (property != null) {
Object value = property.getValue();
if (value instanceof ProtocolConfig && id.equals(((ProtocolConfig) value).getName())) {
definition.getPropertyValues().addPropertyValue("protocol", new RuntimeBeanReference(id));
}
}
}
} else if (ServiceBean.class.equals(beanClass)) {
//直接指定class的方式
String className = element.getAttribute("class");
if (className != null && className.length() > 0) {
RootBeanDefinition classDefinition = new RootBeanDefinition();
//利用反射有类名得到class
classDefinition.setBeanClass(ReflectUtils.forName(className));
classDefinition.setLazyInit(false);
//解析property
parseProperties(element.getChildNodes(), classDefinition);
//把serviceBean 的ref 属性设置为指向class类
beanDefinition.getPropertyValues().addPropertyValue("ref", new BeanDefinitionHolder(classDefinition, id "Impl"));
}
} else if (ProviderConfig.class.equals(beanClass)) {
//proivder的配置 作为ServiceBean 的设置
parseNested(element, parserContext, ServiceBean.class, true, "service", "provider", id, beanDefinition);
} else if (ConsumerConfig.class.equals(beanClass)) {
// consumer的配置 作为ReferenceBean 的设置
parseNested(element, parserContext, ReferenceBean.class, false, "reference", "consumer", id, beanDefinition);
}
Set<String> props = new HashSet<String>();
ManagedMap parameters = null;
for (Method setter : beanClass.getMethods()) {
String name = setter.getName();
if (name.length() > 3 && name.startsWith("set")
&& Modifier.isPublic(setter.getModifiers())
&& setter.getParameterTypes().length == 1) {
//所有只有一个参数的set方法
//set方法参数类型
Class<?> type = setter.getParameterTypes()[0];
//abCdEF --> ab-cd-ef 驼峰命名转换 - 分割
String property = StringUtils.camelToSplitName(name.substring(3, 4).toLowerCase() name.substring(4), "-");
props.add(property);
Method getter = null;
//获取 对应public getter 方法
try {
getter = beanClass.getMethod("get" name.substring(3), new Class<?>[0]);
} catch (NoSuchMethodException e) {
try {
getter = beanClass.getMethod("is" name.substring(3), new Class<?>[0]);
} catch (NoSuchMethodException e2) {
}
}
if (getter == null
|| !Modifier.isPublic(getter.getModifiers())
|| !type.equals(getter.getReturnType())) {
continue;
}
if ("parameters".equals(property)) {//有parameters属性,解析元素的所有parameter元素
parameters = parseParameters(element.getChildNodes(), beanDefinition);
} else if ("methods".equals(property)) {//有methods属性,就解析配置元素的所有method元素 放到beanDefinition “methods” 配置里
parseMethods(id, element.getChildNodes(), beanDefinition, parserContext);
} else if ("arguments".equals(property)) {//有arguments属性,就解析所有的argument元素
parseArguments(id, element.getChildNodes(), beanDefinition, parserContext);
} else {
String value = element.getAttribute(property);
if (value != null) {
value = value.trim();
if (value.length() > 0) {
if ("registry".equals(property) && RegistryConfig.NO_AVAILABLE.equalsIgnoreCase(value)) {
RegistryConfig registryConfig = new RegistryConfig();
registryConfig.setAddress(RegistryConfig.NO_AVAILABLE);
beanDefinition.getPropertyValues().addPropertyValue(property, registryConfig);
} else if ("registry".equals(property) && value.indexOf(',') != -1) {
//解析多个以逗号分割的多个registry配置 放到 beanDefinition registries属性里
parseMultiRef("registries", value, beanDefinition, parserContext);
} else if ("provider".equals(property) && value.indexOf(',') != -1) {
//解析多个以逗号分割的多个provider配置 放到 beanDefinition providers属性里
parseMultiRef("providers", value, beanDefinition, parserContext);
} else if ("protocol".equals(property) && value.indexOf(',') != -1) {
//解析多个以逗号分割的多个protocol配置 放到 beanDefinition protocols属性里
parseMultiRef("protocols", value, beanDefinition, parserContext);
} else {
Object reference;
if (isPrimitive(type)) {//set 方法参数是方法指定的原始类型
if ("async".equals(property) && "false".equals(value)
|| "timeout".equals(property) && "0".equals(value)
|| "delay".equals(property) && "0".equals(value)
|| "version".equals(property) && "0.0.0".equals(value)
|| "stat".equals(property) && "-1".equals(value)
|| "reliable".equals(property) && "false".equals(value)) {
// 兼容旧版本xsd中的default值
value = null;
}
//直接赋值
reference = value;
} else if ("protocol".equals(property)
&& ExtensionLoader.getExtensionLoader(Protocol.class).hasExtension(value)
&& (!parserContext.getRegistry().containsBeanDefinition(value)
|| !ProtocolConfig.class.getName().equals(parserContext.getRegistry().getBeanDefinition(value).getBeanClassName()))) {
if ("dubbo:provider".equals(element.getTagName())) {
logger.warn("Recommended replace <dubbo:provider protocol="" value "" ... /> to <dubbo:protocol name="" value "" ... />");
}
//兼容旧版本配置
ProtocolConfig protocol = new ProtocolConfig();
protocol.setName(value);
reference = protocol;
} else if ("monitor".equals(property)
&& (!parserContext.getRegistry().containsBeanDefinition(value)
|| !MonitorConfig.class.getName().equals(parserContext.getRegistry().getBeanDefinition(value).getBeanClassName()))) {
//兼容旧版本配置
reference = convertMonitor(value);
} else if ("onreturn".equals(property)) {//回调函数设置 service.ontrenMethod
int index = value.lastIndexOf(".");
String returnRef = value.substring(0, index);
String returnMethod = value.substring(index 1);
reference = new RuntimeBeanReference(returnRef);
beanDefinition.getPropertyValues().addPropertyValue("onreturnMethod", returnMethod);
} else if ("onthrow".equals(property)) {
int index = value.lastIndexOf(".");
String throwRef = value.substring(0, index);
String throwMethod = value.substring(index 1);
reference = new RuntimeBeanReference(throwRef);
beanDefinition.getPropertyValues().addPropertyValue("onthrowMethod", throwMethod);
} else {//解析ref 属性
if ("ref".equals(property) && parserContext.getRegistry().containsBeanDefinition(value)) {
BeanDefinition refBean = parserContext.getRegistry().getBeanDefinition(value);
if (!refBean.isSingleton()) {
throw new IllegalStateException("The exported service ref " value " must be singleton! Please set the " value " bean scope to singleton, eg: <bean id="" value "" scope="singleton" ...>");
}
}
reference = new RuntimeBeanReference(value);
}
beanDefinition.getPropertyValues().addPropertyValue(property, reference);
}
}
}
}
}
}
//element 本身所有属性 放入beanDefinition的parameters
NamedNodeMap attributes = element.getAttributes();
int len = attributes.getLength();
for (int i = 0; i < len; i ) {
Node node = attributes.item(i);
String name = node.getLocalName();
if (!props.contains(name)) {
if (parameters == null) {
parameters = new ManagedMap();
}
String value = node.getNodeValue();
parameters.put(name, new TypedStringValue(value, String.class));
}
}
if (parameters != null) {
beanDefinition.getPropertyValues().addPropertyValue("parameters", parameters);
}
return beanDefinition;
}
ReferenceBean类
ReferenceBean类主要完成在适当的时机(spring bean初始化完成,或者用户通过spring容器获取bean) 根据服务调用方配置,生成服务调用代理的工作。
ReferenceBean继承类层:
可以看到,ReferenceBean及其基类实现了FactoryBean, ApplicationContextAware, InitializingBean, DisposableBean 4个接口的方法, 通过spring回调机制,完成spring容器传入,获取bean类型,bean初始化和destory定制等操作。ReferenceBean类里具体方法实现:
代码语言:javascript复制/***
* 实现ApplicationContextAware接口方法。在bean初始化时,回传bean所在容器的引用
* @param applicationContext
*/
public void setApplicationContext(ApplicationContext applicationContext) {
this.applicationContext = applicationContext;
//容器引用,传入SpringExtensionFactory
SpringExtensionFactory.addApplicationContext(applicationContext);
}
/***
* 实现FactoryBean接口方法,
* 返回一个bean实例,在使用spring api 向容器获取一个bean时调用
* 这里返回的是reference代理
* @return
* @throws Exception
*/
public Object getObject() throws Exception {
return get();
}
/***
* 实现FactoryBean接口方法,
* 返回一个bean的类型
* @return
*/
public Class<?> getObjectType() {
return getInterfaceClass();
}
/***
* 实现FactoryBean接口方法,
* 返回一个bean的是否是单例
* @return
*/
@Parameter(excluded = true)
public boolean isSingleton() {
return true;
}
/***
* 实现InitializingBean接口方法,
* 在bean 所有(提供的)属性值都赋值后,由spring回调执行
* 这个方法里可以做些初始化定制
* @throws Exception
*/
@SuppressWarnings({"unchecked"})
public void afterPropertiesSet() throws Exception {
if (getConsumer() == null) {
//BeanFactoryUtils.beansOfTypeIncludingAncestors是spring的一个工具类,
// 它返回指定容器里,ConsumerConfig.class类及其子类的bean,如果还没初始化,会触发初始化的过程,依赖注入的概念
Map<String, ConsumerConfig> consumerConfigMap = applicationContext == null ? null : BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, ConsumerConfig.class, false, false);
if (consumerConfigMap != null && consumerConfigMap.size() > 0) {
ConsumerConfig consumerConfig = null;
//遍历map 默认设置ConsumerConfig
for (ConsumerConfig config : consumerConfigMap.values()) {
if (config.isDefault() == null || config.isDefault().booleanValue()) {
if (consumerConfig != null) {
throw new IllegalStateException("Duplicate consumer configs: " consumerConfig " and " config);
}
consumerConfig = config;
}
}
//设置ConsumerConfig
if (consumerConfig != null) {
setConsumer(consumerConfig);
}
}
}
//设置ApplicationConfig
if (getApplication() == null
&& (getConsumer() == null || getConsumer().getApplication() == null)) {
Map<String, ApplicationConfig> applicationConfigMap = applicationContext == null ? null : BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, ApplicationConfig.class, false, false);
if (applicationConfigMap != null && applicationConfigMap.size() > 0) {
ApplicationConfig applicationConfig = null;
for (ApplicationConfig config : applicationConfigMap.values()) {
if (config.isDefault() == null || config.isDefault().booleanValue()) {
if (applicationConfig != null) {
throw new IllegalStateException("Duplicate application configs: " applicationConfig " and " config);
}
applicationConfig = config;
}
}
if (applicationConfig != null) {
setApplication(applicationConfig);
}
}
}
//设置ModuleConfig
if (getModule() == null
&& (getConsumer() == null || getConsumer().getModule() == null)) {
Map<String, ModuleConfig> moduleConfigMap = applicationContext == null ? null : BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, ModuleConfig.class, false, false);
if (moduleConfigMap != null && moduleConfigMap.size() > 0) {
ModuleConfig moduleConfig = null;
for (ModuleConfig config : moduleConfigMap.values()) {
if (config.isDefault() == null || config.isDefault().booleanValue()) {
if (moduleConfig != null) {
throw new IllegalStateException("Duplicate module configs: " moduleConfig " and " config);
}
moduleConfig = config;
}
}
if (moduleConfig != null) {
setModule(moduleConfig);
}
}
}
//注册中心可以有多个
if ((getRegistries() == null || getRegistries().size() == 0)
&& (getConsumer() == null || getConsumer().getRegistries() == null || getConsumer().getRegistries().size() == 0)
&& (getApplication() == null || getApplication().getRegistries() == null || getApplication().getRegistries().size() == 0)) {
//多个注册中心
Map<String, RegistryConfig> registryConfigMap = applicationContext == null ? null : BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, RegistryConfig.class, false, false);
if (registryConfigMap != null && registryConfigMap.size() > 0) {
List<RegistryConfig> registryConfigs = new ArrayList<RegistryConfig>();
for (RegistryConfig config : registryConfigMap.values()) {
if (config.isDefault() == null || config.isDefault().booleanValue()) {
registryConfigs.add(config);
}
}
if (registryConfigs != null && registryConfigs.size() > 0) {
super.setRegistries(registryConfigs);
}
}
}
//设置监控中心
if (getMonitor() == null
&& (getConsumer() == null || getConsumer().getMonitor() == null)
&& (getApplication() == null || getApplication().getMonitor() == null)) {
Map<String, MonitorConfig> monitorConfigMap = applicationContext == null ? null : BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, MonitorConfig.class, false, false);
if (monitorConfigMap != null && monitorConfigMap.size() > 0) {
MonitorConfig monitorConfig = null;
for (MonitorConfig config : monitorConfigMap.values()) {
if (config.isDefault() == null || config.isDefault().booleanValue()) {
if (monitorConfig != null) {
throw new IllegalStateException("Duplicate monitor configs: " monitorConfig " and " config);
}
monitorConfig = config;
}
}
if (monitorConfig != null) {
setMonitor(monitorConfig);
}
}
}
//是否bean创建后就初始化代理
Boolean b = isInit();
if (b == null && getConsumer() != null) {
b = getConsumer().isInit();
}
if (b != null && b.booleanValue()) {//立即初始化代理
getObject();
}
}
ServiceBean类
ServiceBean类主要完成,在适当的时机(spring 容器初始化完成或者服务实例初始化完成)根据服务提供方配置暴露发布服务的工作。ServiceBean类继承层如下:
可以看到ServiceBean及其基类实现了InitializingBean, DisposableBean, ApplicationContextAware, ApplicationListener, BeanNameAware接口 通过spring回调机制完成spring容器引用传入,bean初始化和destory过程定制,以及监听并处理spring事件的操作。ServiceBean类具体方法实现:
代码语言:javascript复制/***
* ApplicationContextAware接口方法,
* 传入bean 所在容器引用
* @param applicationContext
*/
public void setApplicationContext(ApplicationContext applicationContext) {
this.applicationContext = applicationContext;
//把spring 容器传入SpringExtensionFactory
SpringExtensionFactory.addApplicationContext(applicationContext);
//获取容器addApplicationListener方法,把当前类加入到容器监听器队列
if (applicationContext != null) {
SPRING_CONTEXT = applicationContext;
try {
Method method = applicationContext.getClass().getMethod("addApplicationListener", new Class<?>[]{ApplicationListener.class}); // 兼容Spring2.0.1
method.invoke(applicationContext, new Object[]{this});
supportedApplicationListener = true;
} catch (Throwable t) {
if (applicationContext instanceof AbstractApplicationContext) {
try {
Method method = AbstractApplicationContext.class.getDeclaredMethod("addListener", new Class<?>[]{ApplicationListener.class}); // 兼容Spring2.0.1
if (!method.isAccessible()) {
method.setAccessible(true);
}
method.invoke(applicationContext, new Object[]{this});
supportedApplicationListener = true;
} catch (Throwable t2) {
}
}
}
}
}
/***
* BeanNameAware接口方法,设置beanName值
* @param name
*/
public void setBeanName(String name) {
this.beanName = name;
}
/***
* 实现ApplicationListener接口方法,
* 本方法会接受并处理在容器初始化完成时发布的ContextRefreshedEvent事件,
* 即容器初始化完成后 暴露服务
* @param event
*/
public void onApplicationEvent(ApplicationEvent event) {
if (ContextRefreshedEvent.class.getName().equals(event.getClass().getName())) {
if (isDelay() && !isExported() && !isUnexported()) {
if (logger.isInfoEnabled()) {
logger.info("The service ready on spring started. service: " getInterface());
}
//执行暴露过程
export();
}
}
}
/***
* InitializingBean 接口方法,bean 属性初始化后,操作处理
* @throws Exception
*/
@SuppressWarnings({"unchecked", "deprecation"})
public void afterPropertiesSet() throws Exception {
//设置ProviderConfig
if (getProvider() == null) {
Map<String, ProviderConfig> providerConfigMap = applicationContext == null ? null : BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, ProviderConfig.class, false, false);
if (providerConfigMap != null && providerConfigMap.size() > 0) {
Map<String, ProtocolConfig> protocolConfigMap = applicationContext == null ? null : BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, ProtocolConfig.class, false, false);
if ((protocolConfigMap == null || protocolConfigMap.size() == 0)
&& providerConfigMap.size() > 1) { // 兼容旧版本
List<ProviderConfig> providerConfigs = new ArrayList<ProviderConfig>();
for (ProviderConfig config : providerConfigMap.values()) {
if (config.isDefault() != null && config.isDefault().booleanValue()) {
providerConfigs.add(config);
}
}
if (providerConfigs.size() > 0) {
setProviders(providerConfigs);
}
} else {
ProviderConfig providerConfig = null;
for (ProviderConfig config : providerConfigMap.values()) {
if (config.isDefault() == null || config.isDefault().booleanValue()) {
if (providerConfig != null) {
throw new IllegalStateException("Duplicate provider configs: " providerConfig " and " config);
}
providerConfig = config;
}
}
if (providerConfig != null) {
setProvider(providerConfig);
}
}
}
}
if (getApplication() == null
&& (getProvider() == null || getProvider().getApplication() == null)) {
Map<String, ApplicationConfig> applicationConfigMap = applicationContext == null ? null : BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, ApplicationConfig.class, false, false);
if (applicationConfigMap != null && applicationConfigMap.size() > 0) {
ApplicationConfig applicationConfig = null;
for (ApplicationConfig config : applicationConfigMap.values()) {
if (config.isDefault() == null || config.isDefault().booleanValue()) {
if (applicationConfig != null) {
throw new IllegalStateException("Duplicate application configs: " applicationConfig " and " config);
}
applicationConfig = config;
}
}
if (applicationConfig != null) {
setApplication(applicationConfig);
}
}
}
if (getModule() == null
&& (getProvider() == null || getProvider().getModule() == null)) {
Map<String, ModuleConfig> moduleConfigMap = applicationContext == null ? null : BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, ModuleConfig.class, false, false);
if (moduleConfigMap != null && moduleConfigMap.size() > 0) {
ModuleConfig moduleConfig = null;
for (ModuleConfig config : moduleConfigMap.values()) {
if (config.isDefault() == null || config.isDefault().booleanValue()) {
if (moduleConfig != null) {
throw new IllegalStateException("Duplicate module configs: " moduleConfig " and " config);
}
moduleConfig = config;
}
}
if (moduleConfig != null) {
setModule(moduleConfig);
}
}
}
if ((getRegistries() == null || getRegistries().size() == 0)
&& (getProvider() == null || getProvider().getRegistries() == null || getProvider().getRegistries().size() == 0)
&& (getApplication() == null || getApplication().getRegistries() == null || getApplication().getRegistries().size() == 0)) {
Map<String, RegistryConfig> registryConfigMap = applicationContext == null ? null : BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, RegistryConfig.class, false, false);
if (registryConfigMap != null && registryConfigMap.size() > 0) {
List<RegistryConfig> registryConfigs = new ArrayList<RegistryConfig>();
for (RegistryConfig config : registryConfigMap.values()) {
if (config.isDefault() == null || config.isDefault().booleanValue()) {
registryConfigs.add(config);
}
}
if (registryConfigs != null && registryConfigs.size() > 0) {
super.setRegistries(registryConfigs);
}
}
}
if (getMonitor() == null
&& (getProvider() == null || getProvider().getMonitor() == null)
&& (getApplication() == null || getApplication().getMonitor() == null)) {
Map<String, MonitorConfig> monitorConfigMap = applicationContext == null ? null : BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, MonitorConfig.class, false, false);
if (monitorConfigMap != null && monitorConfigMap.size() > 0) {
MonitorConfig monitorConfig = null;
for (MonitorConfig config : monitorConfigMap.values()) {
if (config.isDefault() == null || config.isDefault().booleanValue()) {
if (monitorConfig != null) {
throw new IllegalStateException("Duplicate monitor configs: " monitorConfig " and " config);
}
monitorConfig = config;
}
}
if (monitorConfig != null) {
setMonitor(monitorConfig);
}
}
}
//服务协议,可以有多个
if ((getProtocols() == null || getProtocols().size() == 0)
&& (getProvider() == null || getProvider().getProtocols() == null || getProvider().getProtocols().size() == 0)) {
Map<String, ProtocolConfig> protocolConfigMap = applicationContext == null ? null : BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, ProtocolConfig.class, false, false);
if (protocolConfigMap != null && protocolConfigMap.size() > 0) {
List<ProtocolConfig> protocolConfigs = new ArrayList<ProtocolConfig>();
for (ProtocolConfig config : protocolConfigMap.values()) {
if (config.isDefault() == null || config.isDefault().booleanValue()) {
protocolConfigs.add(config);
}
}
if (protocolConfigs != null && protocolConfigs.size() > 0) {
super.setProtocols(protocolConfigs);
}
}
}
//设置服务路径 类全名
if (getPath() == null || getPath().length() == 0) {
if (beanName != null && beanName.length() > 0
&& getInterface() != null && getInterface().length() > 0
&& beanName.startsWith(getInterface())) {
setPath(beanName);
}
}
//是否延迟暴露
if (!isDelay()) {
export();//暴露服务
}
}
/***
* DisposableBean接口方法,再单例bean 析构时,回调
* 回收资源,这里调用unexport方法
* @throws Exception
*/
public void destroy() throws Exception {
unexport();
}
AnnotationBean类
这个类使得dubbo具有自动包扫描的功能,支持dubbo通过注解配置service和refernece bean(有些属性不能注解配置),并完成ServiceBean和ReferenceBean相同的功能。类图:
可以看到AnnotationBean及其父类实现了接口DisposableBean, BeanFactoryPostProcessor, BeanPostProcessor, ApplicationContextAware同样通过spring接口方法回调,实现bean实例的初始化预处理。
AnnotationBean类是基于ClassPathBeanDefinitionScanner类实现的。 自动包扫描先看下 org.springframework.context.annotation.ClassPathBeanDefinitionScanner类, 官方解释:
代码语言:javascript复制A bean definition scanner that detects bean candidates on the classpath,
registering corresponding bean definitions with a given registry (BeanFactory or ApplicationContext).
Candidate classes are detected through configurable type filters.
The default filters include classes that are annotated with Spring's
@Component, @Repository, @Service, or @Controller stereotype.
说人话,就是ClassPathBeanDefinitionScanner会自动在classpatch里扫描并注册 @Component, @Repository, @Service, or @Controller的beans,相当于自动完成 上面说的DubboBeanDefinitionParser类的类似工作。这个类默认处理上面说的4种注解, 但能通过filter添加新的要扫描处理的注解。主要代码实现:
代码语言:javascript复制 /***
* 设置要扫描的包名,以逗号分隔多个包名
* @param annotationPackage
*/
public void setPackage(String annotationPackage) {
this.annotationPackage = annotationPackage;
this.annotationPackages = (annotationPackage == null || annotationPackage.length() == 0) ? null
: Constants.COMMA_SPLIT_PATTERN.split(annotationPackage);
}
/***
* 实现spring 回调接口方法,传入的容器引用
* @param applicationContext
* @throws BeansException
*/
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
/***
* 实现BeanFactoryPostProcessor接口
* 这个方法会在,所有的bean definitions已加载,
* 但是还没实例化之前回调执行
* 可以在bean初始化之前定制化一些操作
* 这里做的是,调用org.springframework.context.annotation.ClassPathBeanDefinitionScanner的scan方法,
* 扫描并注册有 Service(dubbo定义) 注解的bean
* 当然都是用反射完成的
* @param beanFactory
* @throws BeansException
*/
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)
throws BeansException {
if (annotationPackage == null || annotationPackage.length() == 0) {
return;
}
if (beanFactory instanceof BeanDefinitionRegistry) {
try {
// init scanner
//利用反射构造ClassPathBeanDefinitionScanner实例,用的这个构造方法,
// useDefaultFilters=true 默认扫描 spring 4种的注解
// public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry, boolean useDefaultFilters) {
// this(registry, useDefaultFilters, getOrCreateEnvironment(registry));
// }
Class<?> scannerClass = ReflectUtils.forName("org.springframework.context.annotation.ClassPathBeanDefinitionScanner");
Object scanner = scannerClass.getConstructor(new Class<?>[]{BeanDefinitionRegistry.class, boolean.class}).newInstance(new Object[]{(BeanDefinitionRegistry) beanFactory, true});
// add filter
//通过filter 添加新要扫描的注解,也是用的反射 这里是 AnnotationTypeFilter
Class<?> filterClass = ReflectUtils.forName("org.springframework.core.type.filter.AnnotationTypeFilter");
Object filter = filterClass.getConstructor(Class.class).newInstance(Service.class);
//获取添加filter的方法,并调用
Method addIncludeFilter = scannerClass.getMethod("addIncludeFilter", ReflectUtils.forName("org.springframework.core.type.filter.TypeFilter"));
addIncludeFilter.invoke(scanner, filter);
// scan packages
//获取 ClassPathBeanDefinitionScanner的 scan(java.lang.String... basePackages) 方法,开始扫描
String[] packages = Constants.COMMA_SPLIT_PATTERN.split(annotationPackage);
Method scan = scannerClass.getMethod("scan", new Class<?>[]{String[].class});
scan.invoke(scanner, new Object[]{packages});
} catch (Throwable e) {
// spring 2.0
}
}
}
/***
* 实现DisposableBean接口
* 在bean 析构时,调用相关方法,释放资源
* @throws Exception
*/
public void destroy() throws Exception {
for (ServiceConfig<?> serviceConfig : serviceConfigs) {
try {
serviceConfig.unexport();
} catch (Throwable e) {
logger.error(e.getMessage(), e);
}
}
for (ReferenceConfig<?> referenceConfig : referenceConfigs.values()) {
try {
referenceConfig.destroy();
} catch (Throwable e) {
logger.error(e.getMessage(), e);
}
}
}
/***
* 实现BeanPostProcessor接口方法
* 在bean初始化后 比如在afterPropertiesSet后由spring回调执行
* 这个方法完成类似ServiceBean的工作
* @param bean
* @param beanName
* @return
* @throws BeansException
*/
public Object postProcessAfterInitialization(Object bean, String beanName)
throws BeansException {
//检查是否匹配包名
if (!isMatchPackage(bean)) {
return bean;
}
//手动创建 ServiceBean 并暴露服务
Service service = bean.getClass().getAnnotation(Service.class);
if (service != null) {
ServiceBean<Object> serviceConfig = new ServiceBean<Object>(service);
serviceConfig.setRef(bean);
if (void.class.equals(service.interfaceClass())
&& "".equals(service.interfaceName())) {
if (bean.getClass().getInterfaces().length > 0) {
serviceConfig.setInterface(bean.getClass().getInterfaces()[0]);
} else {
throw new IllegalStateException("Failed to export remote service class " bean.getClass().getName() ", cause: The @Service undefined interfaceClass or interfaceName, and the service class unimplemented any interfaces.");
}
}
if (applicationContext != null) {
serviceConfig.setApplicationContext(applicationContext);
if (service.registry() != null && service.registry().length > 0) {
List<RegistryConfig> registryConfigs = new ArrayList<RegistryConfig>();
for (String registryId : service.registry()) {
if (registryId != null && registryId.length() > 0) {
registryConfigs.add((RegistryConfig) applicationContext.getBean(registryId, RegistryConfig.class));
}
}
serviceConfig.setRegistries(registryConfigs);
}
if (service.provider() != null && service.provider().length() > 0) {
serviceConfig.setProvider((ProviderConfig) applicationContext.getBean(service.provider(), ProviderConfig.class));
}
if (service.monitor() != null && service.monitor().length() > 0) {
serviceConfig.setMonitor((MonitorConfig) applicationContext.getBean(service.monitor(), MonitorConfig.class));
}
if (service.application() != null && service.application().length() > 0) {
serviceConfig.setApplication((ApplicationConfig) applicationContext.getBean(service.application(), ApplicationConfig.class));
}
if (service.module() != null && service.module().length() > 0) {
serviceConfig.setModule((ModuleConfig) applicationContext.getBean(service.module(), ModuleConfig.class));
}
if (service.provider() != null && service.provider().length() > 0) {
serviceConfig.setProvider((ProviderConfig) applicationContext.getBean(service.provider(), ProviderConfig.class));
} else {
}
if (service.protocol() != null && service.protocol().length > 0) {
List<ProtocolConfig> protocolConfigs = new ArrayList<ProtocolConfig>();
for (String protocolId : service.protocol()) {
if (protocolId != null && protocolId.length() > 0) {
protocolConfigs.add((ProtocolConfig) applicationContext.getBean(protocolId, ProtocolConfig.class));
}
}
serviceConfig.setProtocols(protocolConfigs);
}
try {
//调用ServiceBean afterPropertiesSet初始化配置
serviceConfig.afterPropertiesSet();
} catch (RuntimeException e) {
throw (RuntimeException) e;
} catch (Exception e) {
throw new IllegalStateException(e.getMessage(), e);
}
}
serviceConfigs.add(serviceConfig);
//暴露服务
serviceConfig.export();
}
return bean;
}
/***
* /***
* 实现BeanPostProcessor接口方法
* 在bean初始化前 比如在afterPropertiesSet前 由spring 回调执行
* 这个方法完成类似RefercencBean的工作
* @param bean
* @param beanName
* @return
* @throws BeansException
*/
public Object postProcessBeforeInitialization(Object bean, String beanName)
throws BeansException {
if (!isMatchPackage(bean)) {
return bean;
}
//因为dubbo Reference 注解只能在类的字段,或方法上
//通过bean 的set 方法上 找duboo 注解
Method[] methods = bean.getClass().getMethods();
for (Method method : methods) {
String name = method.getName();
if (name.length() > 3 && name.startsWith("set")
&& method.getParameterTypes().length == 1
&& Modifier.isPublic(method.getModifiers())
&& !Modifier.isStatic(method.getModifiers())) {
try {
Reference reference = method.getAnnotation(Reference.class);
if (reference != null) {
Object value = refer(reference, method.getParameterTypes()[0]);
if (value != null) {
method.invoke(bean, new Object[]{value});
}
}
} catch (Throwable e) {
logger.error("Failed to init remote service reference at method " name " in class " bean.getClass().getName() ", cause: " e.getMessage(), e);
}
}
}
//通过bean 的字段 上 找duboo 注解
Field[] fields = bean.getClass().getDeclaredFields();
for (Field field : fields) {
try {
if (!field.isAccessible()) {
field.setAccessible(true);
}
Reference reference = field.getAnnotation(Reference.class);
if (reference != null) {
Object value = refer(reference, field.getType());
if (value != null) {
field.set(bean, value);
}
}
} catch (Throwable e) {
logger.error("Failed to init remote service reference at filed " field.getName() " in class " bean.getClass().getName() ", cause: " e.getMessage(), e);
}
}
return bean;
}
/***
* 通过解析 reference注解里的值,去构造服务调用配置,最后调用创建代理的方法
* @param reference
* @param referenceClass
* @return
*/
private Object refer(Reference reference, Class<?> referenceClass) { //method.getParameterTypes()[0]
String interfaceName;
if (!"".equals(reference.interfaceName())) {
interfaceName = reference.interfaceName();
} else if (!void.class.equals(reference.interfaceClass())) {
interfaceName = reference.interfaceClass().getName();
} else if (referenceClass.isInterface()) {
interfaceName = referenceClass.getName();
} else {
throw new IllegalStateException("The @Reference undefined interfaceClass or interfaceName, and the property type " referenceClass.getName() " is not a interface.");
}
String key = reference.group() "/" interfaceName ":" reference.version();
ReferenceBean<?> referenceConfig = referenceConfigs.get(key);
if (referenceConfig == null) {
referenceConfig = new ReferenceBean<Object>(reference);
if (void.class.equals(reference.interfaceClass())
&& "".equals(reference.interfaceName())
&& referenceClass.isInterface()) {
referenceConfig.setInterface(referenceClass);
}
if (applicationContext != null) {
referenceConfig.setApplicationContext(applicationContext);
if (reference.registry() != null && reference.registry().length > 0) {
List<RegistryConfig> registryConfigs = new ArrayList<RegistryConfig>();
for (String registryId : reference.registry()) {
if (registryId != null && registryId.length() > 0) {
registryConfigs.add((RegistryConfig) applicationContext.getBean(registryId, RegistryConfig.class));
}
}
referenceConfig.setRegistries(registryConfigs);
}
if (reference.consumer() != null && reference.consumer().length() > 0) {
referenceConfig.setConsumer((ConsumerConfig) applicationContext.getBean(reference.consumer(), ConsumerConfig.class));
}
if (reference.monitor() != null && reference.monitor().length() > 0) {
referenceConfig.setMonitor((MonitorConfig) applicationContext.getBean(reference.monitor(), MonitorConfig.class));
}
if (reference.application() != null && reference.application().length() > 0) {
referenceConfig.setApplication((ApplicationConfig) applicationContext.getBean(reference.application(), ApplicationConfig.class));
}
if (reference.module() != null && reference.module().length() > 0) {
referenceConfig.setModule((ModuleConfig) applicationContext.getBean(reference.module(), ModuleConfig.class));
}
if (reference.consumer() != null && reference.consumer().length() > 0) {
referenceConfig.setConsumer((ConsumerConfig) applicationContext.getBean(reference.consumer(), ConsumerConfig.class));
}
try {
referenceConfig.afterPropertiesSet();
} catch (RuntimeException e) {
throw (RuntimeException) e;
} catch (Exception e) {
throw new IllegalStateException(e.getMessage(), e);
}
}
referenceConfigs.putIfAbsent(key, referenceConfig);
referenceConfig = referenceConfigs.get(key);
}
//服务调用的代理创建
return referenceConfig.get();
}