Dubbo注册dubbo服务的源码分析
来源:互联网 发布:钱箱测试软件 编辑:程序博客网 时间:2024/04/30 13:21
在写代码之前先看一下dubbo
的源码
Dubbo的基本用法可以查看我的博客
http://www.qbmmj.com/tag/dubbo/
dubbo
可以通过xml
的方式或者注解
的方式来配置注册到注册中心的服务
下边先看看一xml
的方式是怎么工作的,在dubbo
的源码包目录下我们可以发现两个spring
的文件,如下图↓
让我们再看看最看是使用xml配置是的配置文件的头部部分,如下图↓
当加载到这个配置文件的时候,就会加载到dubbo,再让我们看看spring.handlers
这个文件,下边是他的代码↓
http\://code.alibabatech.com/schema/dubbo=com.alibaba.dubbo.config.spring.schema.DubboNamespaceHandler
让我们看看这个类,下边是源码↓
/* * Copyright 1999-2011 Alibaba Group. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */package com.alibaba.dubbo.config.spring.schema;import org.springframework.beans.factory.xml.NamespaceHandlerSupport;import com.alibaba.dubbo.common.Version;import com.alibaba.dubbo.config.ApplicationConfig;import com.alibaba.dubbo.config.ConsumerConfig;import com.alibaba.dubbo.config.ModuleConfig;import com.alibaba.dubbo.config.MonitorConfig;import com.alibaba.dubbo.config.ProtocolConfig;import com.alibaba.dubbo.config.ProviderConfig;import com.alibaba.dubbo.config.RegistryConfig;import com.alibaba.dubbo.config.spring.AnnotationBean;import com.alibaba.dubbo.config.spring.ReferenceBean;import com.alibaba.dubbo.config.spring.ServiceBean;/** * 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)); }}
这个类继承了NamespaceHandlerSupport
他有个顶级接口NamespaceHandler
,parse
和decorate
方法在NamespaceHandlerSupport
中已有实现,这时候DubboNamespaceHandler
实现了init
方法,并做了一个版本号的容错的检查,是一个静态块。这个类的目的是解析dubbo
的标签,当spring容器在启动时会掉用到DubboNamespaceHandler
中的init
方法,通过查看源码阔以发现对标签中的bean
的处理是通过DubboBeanDefinitionParser
来处理的,这个类实现了BeanDefinitionParser
接口重写了pase
方法在pase
中调用了一个静态的pase
方法去做处理。通过在构造中传入不同的参数来解析不同的Dubbo
标签。
到此为止将xml转换为spring
的bean定义的操作已经结束了。下边再看看比较核心的serviceBean
的创建↓
先看看ServiceBean
的源码,下边贴出源码↓
/* * Copyright 1999-2011 Alibaba Group. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */package com.alibaba.dubbo.config.spring;import java.lang.reflect.Method;import java.util.ArrayList;import java.util.List;import java.util.Map;import org.springframework.beans.factory.BeanFactoryUtils;import org.springframework.beans.factory.BeanNameAware;import org.springframework.beans.factory.DisposableBean;import org.springframework.beans.factory.InitializingBean;import org.springframework.context.ApplicationContext;import org.springframework.context.ApplicationContextAware;import org.springframework.context.ApplicationEvent;import org.springframework.context.ApplicationListener;import org.springframework.context.event.ContextRefreshedEvent;import org.springframework.context.support.AbstractApplicationContext;import com.alibaba.dubbo.config.ApplicationConfig;import com.alibaba.dubbo.config.ModuleConfig;import com.alibaba.dubbo.config.MonitorConfig;import com.alibaba.dubbo.config.ProtocolConfig;import com.alibaba.dubbo.config.ProviderConfig;import com.alibaba.dubbo.config.RegistryConfig;import com.alibaba.dubbo.config.ServiceConfig;import com.alibaba.dubbo.config.annotation.Service;import com.alibaba.dubbo.config.spring.extension.SpringExtensionFactory;/** * ServiceFactoryBean * * @author william.liangf * @export */public class ServiceBean<T> extends ServiceConfig<T> implements InitializingBean, DisposableBean, ApplicationContextAware, ApplicationListener, BeanNameAware { private static final long serialVersionUID = 213195494150089726L; private static transient ApplicationContext SPRING_CONTEXT; private transient ApplicationContext applicationContext; private transient String beanName; private transient boolean supportedApplicationListener; public ServiceBean() { super(); } public ServiceBean(Service service) { super(service); } public static ApplicationContext getSpringContext() { return SPRING_CONTEXT; } public void setApplicationContext(ApplicationContext applicationContext) { this.applicationContext = applicationContext; SpringExtensionFactory.addApplicationContext(applicationContext); 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) { } } } } } public void setBeanName(String name) { this.beanName = name; } 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(); } } } private boolean isDelay() { Integer delay = getDelay(); ProviderConfig provider = getProvider(); if (delay == null && provider != null) { delay = provider.getDelay(); } return supportedApplicationListener && (delay == null || delay.intValue() == -1); } @SuppressWarnings({ "unchecked", "deprecation" }) public void afterPropertiesSet() throws Exception { 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(); } } public void destroy() throws Exception { unexport(); }}
通过源码阔以发现这个类继承了ServiceConfig
实现了五个接口,分别是InitializingBean
,DisposableBean
,ApplicationContextAware
,ApplicationListener
,BeanNameAware
,下边分析
1.首先是InitializingBean
,DisposableBean
Spring
bean的创建和销毁大概有三种方式:①一种是通过注解指定@PostConstruct 和 @PreDestroy 方法②如果是xml
则可以指定init-method
和destory-method
③则是通过实现两个接口来实现InitializingBean
,DisposableBean
。
2.ApplicationContextAware
通过这个接口我们可以拿到spring的上下文
3.ApplicationListener
这个借口的作用是可以监听到所用通过applicationContext.publistEvent(ApplicationEvent event))发布的事件,在spring
启动时bean
初始化完成时会调用publistEvent
发布时间,只要是实现了ApplicationListener
接口的类都可以接收到时间并作出响应。查看源码阔以发现这里监听的是ContextRefreshedEvent
,下边是代码↓
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(); } } }
4.BeanNameAware
通过这个Bean
可以获取到自己在容器中的名字
通过上边分析我们看看源码实现
public void setApplicationContext(ApplicationContext applicationContext) { this.applicationContext = applicationContext; SpringExtensionFactory.addApplicationContext(applicationContext); if (applicationContext != null) { SPRING_CONTEXT = applicationContext; try { //获取容器的`addApplicationListener`方法 Method method = applicationContext.getClass().getMethod("addApplicationListener", new Class<?>[]{ApplicationListener.class}); // 兼容Spring2.0.1 //通过反射调用`addApplicationListener`是当前类监听当前类的创建完成后的事件 method.invoke(applicationContext, new Object[] {this}); //将支持容器监听属性设置为true 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) { } } } } }
接到事件后的处理
public void onApplicationEvent(ApplicationEvent event) { //判断是不是ContextRefreshedEvent 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(); } } }
再看看afterPropertiesSet
这个函数的操作,这个函数的大致意思是当所有的属性都设置到后,做一些属性的校验,校验完了后,就暴露服务
关于停止暴露服务就很简单了,这里直接调用了父类的unexport
方法。
上边是xml
的服务注册,下边在看看注解的方式是怎么实现的,在配置配置文件的时候(或者java代码的方式),我们在容器中实例化了一个bean,这个bean是AnnotationBean
,这个类在com.alibaba.dubbo.config.spring.AnnotationBean
,下边贴出他的代码已做备注
/* * Copyright 1999-2012 Alibaba Group. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */package com.alibaba.dubbo.config.spring;import java.lang.reflect.Field;import java.lang.reflect.Method;import java.lang.reflect.Modifier;import java.util.ArrayList;import java.util.List;import java.util.Set;import java.util.concurrent.ConcurrentHashMap;import java.util.concurrent.ConcurrentMap;import org.springframework.beans.BeansException;import org.springframework.beans.factory.DisposableBean;import org.springframework.beans.factory.config.BeanFactoryPostProcessor;import org.springframework.beans.factory.config.BeanPostProcessor;import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;import org.springframework.beans.factory.support.BeanDefinitionRegistry;import org.springframework.context.ApplicationContext;import org.springframework.context.ApplicationContextAware;import com.alibaba.dubbo.common.Constants;import com.alibaba.dubbo.common.logger.Logger;import com.alibaba.dubbo.common.logger.LoggerFactory;import com.alibaba.dubbo.common.utils.ConcurrentHashSet;import com.alibaba.dubbo.common.utils.ReflectUtils;import com.alibaba.dubbo.config.AbstractConfig;import com.alibaba.dubbo.config.ApplicationConfig;import com.alibaba.dubbo.config.ConsumerConfig;import com.alibaba.dubbo.config.ModuleConfig;import com.alibaba.dubbo.config.MonitorConfig;import com.alibaba.dubbo.config.ProtocolConfig;import com.alibaba.dubbo.config.ProviderConfig;import com.alibaba.dubbo.config.ReferenceConfig;import com.alibaba.dubbo.config.RegistryConfig;import com.alibaba.dubbo.config.ServiceConfig;import com.alibaba.dubbo.config.annotation.Reference;import com.alibaba.dubbo.config.annotation.Service;/** * AnnotationBean * * @author william.liangf * @export */public class AnnotationBean extends AbstractConfig implements DisposableBean, BeanFactoryPostProcessor, BeanPostProcessor, ApplicationContextAware { private static final long serialVersionUID = -7582802454287589552L; private static final Logger logger = LoggerFactory.getLogger(Logger.class); private String annotationPackage; private String[] annotationPackages; private final Set<ServiceConfig<?>> serviceConfigs = new ConcurrentHashSet<ServiceConfig<?>>(); private final ConcurrentMap<String, ReferenceBean<?>> referenceConfigs = new ConcurrentHashMap<String, ReferenceBean<?>>(); public String getPackage() { return annotationPackage; } public void setPackage(String annotationPackage) { this.annotationPackage = annotationPackage; this.annotationPackages = (annotationPackage == null || annotationPackage.length() == 0) ? null : Constants.COMMA_SPLIT_PATTERN.split(annotationPackage); } private ApplicationContext applicationContext; public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { this.applicationContext = applicationContext; } public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { if (annotationPackage == null || annotationPackage.length() == 0) { return; } if (beanFactory instanceof BeanDefinitionRegistry) { try { // init scanner 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 Class<?> filterClass = ReflectUtils.forName("org.springframework.core.type.filter.AnnotationTypeFilter"); Object filter = filterClass.getConstructor(Class.class).newInstance(Service.class); Method addIncludeFilter = scannerClass.getMethod("addIncludeFilter", ReflectUtils.forName("org.springframework.core.type.filter.TypeFilter")); addIncludeFilter.invoke(scanner, filter); // scan packages 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 } } } 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); } } } public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { if (! isMatchPackage(bean)) { return bean; } Service service = bean.getClass().getAnnotation(Service.class); if (service != null) { ServiceBean<Object> serviceConfig = new ServiceBean<Object>(service); 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.registry()) { if (protocolId != null && protocolId.length() > 0) { protocolConfigs.add((ProtocolConfig)applicationContext.getBean(protocolId, ProtocolConfig.class)); } } serviceConfig.setProtocols(protocolConfigs); } try { serviceConfig.afterPropertiesSet(); } catch (RuntimeException e) { throw (RuntimeException) e; } catch (Exception e) { throw new IllegalStateException(e.getMessage(), e); } } serviceConfig.setRef(bean); serviceConfigs.add(serviceConfig); serviceConfig.export(); } return bean; } public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { if (! isMatchPackage(bean)) { return bean; } 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[] { }); } } } catch (Throwable e) { logger.error("Failed to init remote service reference at method " + name + " in class " + bean.getClass().getName() + ", cause: " + e.getMessage(), e); } } } 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; } 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(); } private boolean isMatchPackage(Object bean) { if (annotationPackages == null || annotationPackages.length == 0) { return true; } String beanClassName = bean.getClass().getName(); for (String pkg : annotationPackages) { if (beanClassName.startsWith(pkg)) { return true; } } return false; }}
从代码上看出这个类继承了AbstractConfig
,实现了四个接口DisposableBean
, BeanFactoryPostProcessor
, BeanPostProcessor
, ApplicationContextAware
,下边分析下流程
BeanFactoryPostProcessor
是容器后置处理器,spring容器在启动时会调用到这个接口中的postProcessBeanFactory
实现
BeanPostProcessor
是bean后置处理器,这个接口有两个函数需要实现postProcessBeforeInitialization
初始化之前postProcessAfterInitialization
初始化之后。在初始化bean的时候会调用到这两个函数的实现。
下边先看看postProcessBeanFactory
这个函数会在postProcessBeforeInitialization
之前调用,他的作用很简单,就是找到dubbo的bean,下边看看代码↓
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { //判断package是否有效 if(this.annotationPackage != null && this.annotationPackage.length() != 0) { if(beanFactory instanceof BeanDefinitionRegistry) { try { //加载spring的ClassPathBeanDefinitionScanner类 Class<?> scannerClass = ReflectUtils.forName("org.springframework.context.annotation.ClassPathBeanDefinitionScanner"); //实例化ClassPathBeanDefinitionScanner,将beanFactory作为构造参数传入 Object scanner = scannerClass.getConstructor(new Class[]{BeanDefinitionRegistry.class, Boolean.TYPE}).newInstance(new Object[]{(BeanDefinitionRegistry)beanFactory, Boolean.valueOf(true)}); //加载一个过滤器,只扫描dubbo的service注解 Class<?> filterClass = ReflectUtils.forName("org.springframework.core.type.filter.AnnotationTypeFilter"); Object filter = filterClass.getConstructor(new Class[]{Class.class}).newInstance(new Object[]{Service.class}); //将这个过滤器添加到上边的扫描器中,扫描过滤 Method addIncludeFilter = scannerClass.getMethod("addIncludeFilter", new Class[]{ReflectUtils.forName("org.springframework.core.type.filter.TypeFilter")}); addIncludeFilter.invoke(scanner, new Object[]{filter}); //处理用户设置的扫描的包目录 String[] packages = Constants.COMMA_SPLIT_PATTERN.split(this.annotationPackage); //获取扫描器的scan函数 Method scan = scannerClass.getMethod("scan", new Class[]{String[].class}); //反射调用开始扫描beanDefinition到beanFactory scan.invoke(scanner, new Object[]{packages}); } catch (Throwable var9) { ; } } } }
这个函数的主要作用就是找到dubbo
的ServiceBean
定义,注册到beanFactory
。
然后再看看bean的创建部分,postProcessBeforeInitialization
函数的工作
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { if(!this.isMatchPackage(bean)) { return bean; } else { Method[] methods = bean.getClass().getMethods(); Method[] arr$ = methods; int len$ = methods.length; int len$; Reference reference; Object value; for(len$ = 0; len$ < len$; ++len$) { Method method = arr$[len$]; 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) { value = this.refer(reference, method.getParameterTypes()[0]); if(value != null) { method.invoke(bean, new Object[0]); } } } catch (Throwable var12) { logger.error("Failed to init remote service reference at method " + name + " in class " + bean.getClass().getName() + ", cause: " + var12.getMessage(), var12); } } } Field[] fields = bean.getClass().getDeclaredFields(); Field[] arr$ = fields; len$ = fields.length; for(int i$ = 0; i$ < len$; ++i$) { Field field = arr$[i$]; try { if(!field.isAccessible()) { field.setAccessible(true); } reference = (Reference)field.getAnnotation(Reference.class); if(reference != null) { value = this.refer(reference, field.getType()); if(value != null) { field.set(bean, value); } } } catch (Throwable var11) { logger.error("Failed to init remote service reference at filed " + field.getName() + " in class " + bean.getClass().getName() + ", cause: " + var11.getMessage(), var11); } } return bean; } }
这个方法做的很简单,就是通过set方法来给属性赋值,返回赋值完后的bean。
下边看看postProcessAfterInitialization
代码
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { if(!this.isMatchPackage(bean)) { return bean; } else { Service service = (Service)bean.getClass().getAnnotation(Service.class); if(service != null) { ServiceBean<Object> serviceConfig = new ServiceBean(service); if(Void.TYPE.equals(service.interfaceClass()) && "".equals(service.interfaceName())) { if(bean.getClass().getInterfaces().length <= 0) { 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."); } serviceConfig.setInterface(bean.getClass().getInterfaces()[0]); } if(this.applicationContext != null) { serviceConfig.setApplicationContext(this.applicationContext); ArrayList protocolConfigs; String[] arr$; int len$; int i$; String protocolId; if(service.registry() != null && service.registry().length > 0) { protocolConfigs = new ArrayList(); arr$ = service.registry(); len$ = arr$.length; for(i$ = 0; i$ < len$; ++i$) { protocolId = arr$[i$]; if(protocolId != null && protocolId.length() > 0) { protocolConfigs.add((RegistryConfig)this.applicationContext.getBean(protocolId, RegistryConfig.class)); } } serviceConfig.setRegistries(protocolConfigs); } if(service.provider() != null && service.provider().length() > 0) { serviceConfig.setProvider((ProviderConfig)this.applicationContext.getBean(service.provider(), ProviderConfig.class)); } if(service.monitor() != null && service.monitor().length() > 0) { serviceConfig.setMonitor((MonitorConfig)this.applicationContext.getBean(service.monitor(), MonitorConfig.class)); } if(service.application() != null && service.application().length() > 0) { serviceConfig.setApplication((ApplicationConfig)this.applicationContext.getBean(service.application(), ApplicationConfig.class)); } if(service.module() != null && service.module().length() > 0) { serviceConfig.setModule((ModuleConfig)this.applicationContext.getBean(service.module(), ModuleConfig.class)); } if(service.provider() != null && service.provider().length() > 0) { serviceConfig.setProvider((ProviderConfig)this.applicationContext.getBean(service.provider(), ProviderConfig.class)); } if(service.protocol() != null && service.protocol().length > 0) { protocolConfigs = new ArrayList(); arr$ = service.registry(); len$ = arr$.length; for(i$ = 0; i$ < len$; ++i$) { protocolId = arr$[i$]; if(protocolId != null && protocolId.length() > 0) { protocolConfigs.add((ProtocolConfig)this.applicationContext.getBean(protocolId, ProtocolConfig.class)); } } serviceConfig.setProtocols(protocolConfigs); } try { serviceConfig.afterPropertiesSet(); } catch (RuntimeException var10) { throw var10; } catch (Exception var11) { throw new IllegalStateException(var11.getMessage(), var11); } } serviceConfig.setRef(bean); this.serviceConfigs.add(serviceConfig); serviceConfig.export(); } return bean; } }
有代码看出这个函数在做的事是校验属性,设置ref添加serviceConfig到serviceConfigs,正确无误后调用export到注册中心的操作。
到此为止,代码分析完毕!
http://www.qbmmj.com/2017/07/21/dubbode-fu-wu-zhu-ce-yan-jiu/
- Dubbo注册dubbo服务的源码分析
- Dubbo源码分析系列-服务的发布
- Dubbo源码分析系列-服务的引用
- dubbo源码分析-服务发布
- Dubbo暴露服务和引用服务的实现源码分析
- Dubbo暴露服务和引用服务的实现源码分析
- Docker dubbo 服务注册
- dubbo 服务注册
- dubbo服务注册
- Dubbo源码分析之三:服务的暴露
- Dubbo源码分析之四:服务的调用
- Dubbo实现的源码分析
- Dubbo源码分析(十):服务发布
- dubbo消费者注册服务与发现服务源码
- dubbo注册服务IP解析异常及IP解析源码分析
- dubbo注册服务IP解析异常及IP解析源码分析
- 【dubbo】dubbo服务注册三种方式
- Dubbo源码分析(一):Dubbo源码的结构概述
- 在vs2015中编译zxing c++
- C++重定向
- 深度学习中防止过拟合的方法
- 用 Vue 撸一个微博客户端
- HTML5 2017-07-22
- Dubbo注册dubbo服务的源码分析
- zoj1346
- Document root element "form-validation", must match DOCTYPE root "null"
- HTTP 错误代码总结
- JS将搜索关键字标红的方法
- Android_数据操作 SQLites、ViewPager
- mybatis关联查询
- 网易云音乐移动客户端Vue.js
- 用Vue高仿qq音乐官网-pc端