在寫代碼之前先看一下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.fuchenglei.com/2017/07/21/dubbode-fu-wu-zhu-ce-yan-jiu/