dubbo的consumer只需要在配置文件中配置一个接口的地址,并不需要这个接口有具体的实现类,就可以生成这个接口的代理,通过代理远程调用provider中的方法。
和JDK还有CGlib不同,dubbo的consumer生成代理是通过dubbo中的一个com.alibaba.dubbo.common.bytecode.Proxy来生成的,使用了javassist工具来生成代理类的字节码。
如果在代码中使用
Object obj=ApplicationContextUtil.getBean("orderService");
可以发现obj的class并不是com.alibaba.dubbo.common.bytecode.Proxy,而是类似com.alibaba.dubbo.common.bytecode.Proxy26这样的(后面的数字不一定是26),这个Proxy26就是最终生成的代理类,他的父类就是Object,但是有对应接口中的方法。
如果在代码中使用
Map<String,BeanDefinition> map=ApplicationContextUtil.getBeanDefinitions();
BeanDefinition definition=map.get(service);
String className=definition.getBeanClassName();
可以看到className是com.alibaba.dubbo.config.spring.ReferenceBean。
dubbo在spring配置文件中的配置可以是这样的:
<dubbo:reference id="orderService" interface="test.orderService" protocol="dubbo" check="false"/>
<dubbo >标签是由com.alibaba.dubbo.config.spring.schema.DubboNamespaceHandler来解析的。
DubboNamespaceHandler类是这样的
packagecom.alibaba.dubbo.config.spring.schema;
importcom.alibaba.dubbo.common.Version;
importcom.alibaba.dubbo.config.ApplicationConfig;
importcom.alibaba.dubbo.config.ConsumerConfig;
importcom.alibaba.dubbo.config.ModuleConfig;
importcom.alibaba.dubbo.config.MonitorConfig;
importcom.alibaba.dubbo.config.ProtocolConfig;
importcom.alibaba.dubbo.config.ProviderConfig;
importcom.alibaba.dubbo.config.RegistryConfig;
importcom.alibaba.dubbo.config.spring.AnnotationBean;
importcom.alibaba.dubbo.config.spring.ReferenceBean;
importcom.alibaba.dubbo.config.spring.ServiceBean;
importorg.springframework.beans.factory.xml.NamespaceHandlerSupport;
/**
* DubboNamespaceHandler
*
* @author william.liangf
* @export
*/
public class DubboNamespaceHandler extends NamespaceHandlerSupport {
static {
Version.checkDuplicate(DubboNamespaceHandler.class);
}
public void init() {
registerBeanDefinitionParser("application", newDubboBeanDefinitionParser(ApplicationConfig.class, true));
registerBeanDefinitionParser("module", newDubboBeanDefinitionParser(ModuleConfig.class, true));
registerBeanDefinitionParser("registry", newDubboBeanDefinitionParser(RegistryConfig.class, true));
registerBeanDefinitionParser("monitor", newDubboBeanDefinitionParser(MonitorConfig.class, true));
registerBeanDefinitionParser("provider",new DubboBeanDefinitionParser(ProviderConfig.class, true));
registerBeanDefinitionParser("consumer", newDubboBeanDefinitionParser(ConsumerConfig.class, true));
registerBeanDefinitionParser("protocol", newDubboBeanDefinitionParser(ProtocolConfig.class, true));
registerBeanDefinitionParser("service", newDubboBeanDefinitionParser(ServiceBean.class, true));
registerBeanDefinitionParser("reference", newDubboBeanDefinitionParser(ReferenceBean.class, false));
registerBeanDefinitionParser("annotation", newDubboBeanDefinitionParser(AnnotationBean.class, true));
}
}
所以<dubbo:reference>对应的就是com.alibaba.dubbo.config.spring.ReferenceBean
ReferenceBean的定义是这样的:
public class ReferenceBean<T> extends ReferenceConfig<T>
implements FactoryBean,ApplicationContextAware, InitializingBean, DisposableBean
ReferenceBean实现了org.springframework.beans.factory.FactoryBean接口,因此ReferenceBean是一个FactoryBean,spring对FactoryBean不会直接构造他的实现类来作为代理类,而是通过FactoryBean的getObject()方法来获得代理类。
ReferenceBean实现了org.springframework.beans.factory.InitializingBean接口,实现了这个接口的类需要实现afterPropertiesSet()方法,并且在初始化结束后调用该方法。dubbo的consumer的代理类也是在这个方法中生成。
ReferenceBean的afterPropertiesSet()方法是这样的:
@SuppressWarnings({"unchecked"})
public void afterPropertiesSet() throwsException {
if (getConsumer() == null) {
Map<String, ConsumerConfig>consumerConfigMap = applicationContext == null ? null :BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext,ConsumerConfig.class, false, false);
if (consumerConfigMap != null&& consumerConfigMap.size() > 0) {
ConsumerConfig consumerConfig =null;
for (ConsumerConfig config :consumerConfigMap.values()) {
if (config.isDefault() ==null || config.isDefault().booleanValue()) {
if (consumerConfig !=null) {
throw newIllegalStateException("Duplicate consumer configs: " + consumerConfig+ " and " + config);
}
consumerConfig =config;
}
}
if (consumerConfig != null) {
setConsumer(consumerConfig);
}
}
}
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) {
ApplicationConfigapplicationConfig = null;
for (ApplicationConfig config :applicationConfigMap.values()) {
if (config.isDefault() == null ||config.isDefault().booleanValue()) {
if (applicationConfig!= null) {
throw newIllegalStateException("Duplicate application configs: " +applicationConfig + " and " + config);
}
applicationConfig =config;
}
}
if (applicationConfig != null){
setApplication(applicationConfig);
}
}
}
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 newIllegalStateException("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 newIllegalStateException("Duplicate monitor configs: " + monitorConfig +" and " + config);
}
monitorConfig = config;
}
}
if (monitorConfig != null) {
setMonitor(monitorConfig);
}
}
}
Boolean b = isInit();
if (b == null && getConsumer()!= null) {
b = getConsumer().isInit();
}
if (b != null &&b.booleanValue()) {
getObject();
}
}
主要是按照默认的配置初始化了一些属性,最后调用了getObject()方法,得到代理类
getObject()方法:
public Object getObject() throws Exception {
return get();
}
get()方法在ReferenceBean的父类com.alibaba.dubbo.config.ReferenceConfig中:
public synchronized T get() {
if (this.destroyed) {
throw new IllegalStateException("Alreadydestroyed!");
}
if (this.ref == null) {
init();
}
return this.ref;
}
最后调用了init()方法:
private void init() {
if (initialized) {
return;
}
initialized = true;
if (interfaceName == null ||interfaceName.length() == 0) {
throw newIllegalStateException("<dubbo:reference interface=\"\" />interface not allow null!");
}
// 获取消费者全局配置
checkDefault();
appendProperties(this);
if (getGeneric() == null &&getConsumer() != null) {
setGeneric(getConsumer().getGeneric());
}
if (ProtocolUtils.isGeneric(getGeneric())){
interfaceClass =GenericService.class;
} else {
try {
interfaceClass =Class.forName(interfaceName, true, Thread.currentThread()
.getContextClassLoader());
} catch (ClassNotFoundException e){
throw newIllegalStateException(e.getMessage(), e);
}
checkInterfaceAndMethods(interfaceClass, methods);
}
String resolve =System.getProperty(interfaceName);
String resolveFile = null;
if (resolve == null || resolve.length()== 0) {
resolveFile =System.getProperty("dubbo.resolve.file");
if (resolveFile == null ||resolveFile.length() == 0) {
File userResolveFile = newFile(new File(System.getProperty("user.home")),"dubbo-resolve.properties");
if (userResolveFile.exists()) {
resolveFile =userResolveFile.getAbsolutePath();
}
}
if (resolveFile != null &&resolveFile.length() > 0) {
Properties properties = newProperties();
FileInputStream fis = null;
try {
fis = newFileInputStream(new File(resolveFile));
properties.load(fis);
} catch (IOException e) {
throw newIllegalStateException("Unload " + resolveFile + ", cause: "+ e.getMessage(), e);
} finally {
try {
if (null != fis)fis.close();
} catch (IOException e) {
logger.warn(e.getMessage(), e);
}
}
resolve =properties.getProperty(interfaceName);
}
}
if (resolve != null &&resolve.length() > 0) {
url = resolve;
if (logger.isWarnEnabled()) {
if (resolveFile != null&& resolveFile.length() > 0) {
logger.warn("Usingdefault dubbo resolve file " + resolveFile + " replace " +interfaceName + "" + resolve + " to p2p invoke remoteservice.");
} else {
logger.warn("Using -D"+ interfaceName + "=" + resolve + " to p2p invoke remoteservice.");
}
}
}
if (consumer != null) {
if (application == null) {
application =consumer.getApplication();
}
if (module == null) {
module = consumer.getModule();
}
if (registries == null) {
registries =consumer.getRegistries();
}
if (monitor == null) {
monitor =consumer.getMonitor();
}
}
if (module != null) {
if (registries == null) {
registries =module.getRegistries();
}
if (monitor == null) {
monitor = module.getMonitor();
}
}
if (application != null) {
if (registries == null) {
registries =application.getRegistries();
}
if (monitor == null) {
monitor = application.getMonitor();
}
}
checkApplication();
checkStubAndMock(interfaceClass);
Map<String, String> map = newHashMap<String, String>();
Map<Object, Object> attributes =new HashMap<Object, Object>();
map.put(Constants.SIDE_KEY,Constants.CONSUMER_SIDE);
map.put(Constants.DUBBO_VERSION_KEY,Version.getVersion());
map.put(Constants.TIMESTAMP_KEY,String.valueOf(System.currentTimeMillis()));
if (ConfigUtils.getPid() > 0) {
map.put(Constants.PID_KEY,String.valueOf(ConfigUtils.getPid()));
}
if (!isGeneric()) {
String revision =Version.getVersion(interfaceClass, version);
if (revision != null &&revision.length() > 0) {
map.put("revision",revision);
}
String[] methods =Wrapper.getWrapper(interfaceClass).getMethodNames();
if (methods.length == 0) {
logger.warn("NO methodfound in service interface " + interfaceClass.getName());
map.put("methods",Constants.ANY_VALUE);
} else {
map.put("methods",StringUtils.join(new HashSet<String>(Arrays.asList(methods)),","));
}
}
map.put(Constants.INTERFACE_KEY,interfaceName);
appendParameters(map, application);
appendParameters(map, module);
appendParameters(map, consumer,Constants.DEFAULT_KEY);
appendParameters(map, this);
String prifix =StringUtils.getServiceKey(map);
if (methods != null &&methods.size() > 0) {
for (MethodConfig method : methods){
appendParameters(map, method,method.getName());
String retryKey =method.getName() + ".retry";
if (map.containsKey(retryKey)){
String retryValue =map.remove(retryKey);
if("false".equals(retryValue)) {
map.put(method.getName()+ ".retries", "0");
}
}
appendAttributes(attributes,method, prifix + "." + method.getName());
checkAndConvertImplicitConfig(method, map, attributes);
}
}
//attributes通过系统context进行存储.
StaticContext.getSystemContext().putAll(attributes);
ref = createProxy(map);
}
init()方法把配置文件中的配置项经过判断和拼装,最后全放到了一个map中,最后调用createProxy()方法来生成代理类:
@SuppressWarnings({"unchecked","rawtypes", "deprecation"})
private T createProxy(Map<String,String> map) {
URL tmpUrl = new URL("temp","localhost", 0, map);
final boolean isJvmRefer;
if (isInjvm() == null) {
if (url != null &&url.length() > 0) { //指定URL的情况下,不做本地引用
isJvmRefer = false;
} else if(InjvmProtocol.getInjvmProtocol().isInjvmRefer(tmpUrl)) {
//默认情况下如果本地有服务暴露,则引用本地服务.
isJvmRefer = true;
} else {
isJvmRefer = false;
}
} else {
isJvmRefer =isInjvm().booleanValue();
}
if (isJvmRefer) {
URL url = newURL(Constants.LOCAL_PROTOCOL, NetUtils.LOCALHOST, 0,interfaceClass.getName()).addParameters(map);
invoker = refprotocol.refer(interfaceClass,url);
if (logger.isInfoEnabled()) {
logger.info("Using injvmservice " + interfaceClass.getName());
}
} else {
if (url != null &&url.length() > 0) { // 用户指定URL,指定的URL可能是对点对直连地址,也可能是注册中心URL
String[] us =Constants.SEMICOLON_SPLIT_PATTERN.split(url);
if (us != null &&us.length > 0) {
for (String u : us) {
URL url =URL.valueOf(u);
if (url.getPath() ==null || url.getPath().length() == 0) {
url =url.setPath(interfaceName);
}
if(Constants.REGISTRY_PROTOCOL.equals(url.getProtocol())) {
urls.add(url.addParameterAndEncoded(Constants.REFER_KEY,StringUtils.toQueryString(map)));
} else {
urls.add(ClusterUtils.mergeUrl(url, map));
}
}
}
} else { // 通过注册中心配置拼装URL
List<URL> us =loadRegistries(false);
if (us != null &&us.size() > 0) {
for (URL u : us) {
URL monitorUrl =loadMonitor(u);
if (monitorUrl != null){
map.put(Constants.MONITOR_KEY, URL.encode(monitorUrl.toFullString()));
}
urls.add(u.addParameterAndEncoded(Constants.REFER_KEY,StringUtils.toQueryString(map)));
}
}
if (urls == null || urls.size()== 0) {
throw newIllegalStateException("No such any registry to reference " +interfaceName + " on the consumer " + NetUtils.getLocalHost() +" use dubbo version " + Version.getVersion() + ", please config<dubbo:registry address=\"...\" /> to your springconfig.");
}
}
if (urls.size() == 1) {
invoker =refprotocol.refer(interfaceClass, urls.get(0));
} else {
List<Invoker<?>>invokers = new ArrayList<Invoker<?>>();
URL registryURL = null;
for (URL url : urls) {
invokers.add(refprotocol.refer(interfaceClass,url));
if(Constants.REGISTRY_PROTOCOL.equals(url.getProtocol())) {
registryURL = url; // 用了最后一个registry url
}
}
if (registryURL != null) { // 有 注册中心协议的URL
// 对有注册中心的Cluster 只用AvailableCluster
URL u =registryURL.addParameter(Constants.CLUSTER_KEY, AvailableCluster.NAME);
invoker = cluster.join(newStaticDirectory(u, invokers));
} else { // 不是 注册中心的URL
invoker = cluster.join(newStaticDirectory(invokers));
}
}
}
Boolean c = check;
if (c == null && consumer != null){
c = consumer.isCheck();
}
if (c == null) {
c = true; // default true
}
if (c &&!invoker.isAvailable()) {
throw newIllegalStateException("Failed to check the status of the service " +interfaceName + ". No provider available for the service " + (group== null ? "" : group + "/") + interfaceName + (version ==null ? "" : ":" + version) + " from the url " +invoker.getUrl() + " to the consumer " + NetUtils.getLocalHost() +" use dubbo version " + Version.getVersion());
}
if (logger.isInfoEnabled()) {
logger.info("Refer dubboservice " + interfaceClass.getName() + " from url " +invoker.getUrl());
}
// 创建服务代理
return (T)proxyFactory.getProxy(invoker);
}
createProxy()方法加载了和注册中心有关的配置,其中还区分了是否是本地jvm的服务,如果本地有服务,那就直接用本地的。
最后调用proxyFactory.getProxy(this.invoker)方法来生成代理类
proxyFactory是com.alibaba.dubbo.rpc.ProxyFactory接口的实现类,默认由com.alibaba.dubbo.rpc.proxy.javassist.JavassistProxyFactory类来实现,他的getProxy()方法来自他的父类com.alibaba.dubbo.rpc.proxy.AbstractProxyFactory:
public <T> TgetProxy(Invoker<T> invoker) throws RpcException {
Class<?>[] interfaces = null;
String config = invoker.getUrl().getParameter("interfaces");
if (config != null &&config.length() > 0) {
String[] types =Constants.COMMA_SPLIT_PATTERN.split(config);
if (types != null &&types.length > 0) {
interfaces = newClass<?>[types.length + 2];
interfaces[0] =invoker.getInterface();
interfaces[1] =EchoService.class;
for (int i = 0; i <types.length; i++) {
interfaces[i + 1] =ReflectUtils.forName(types[i]);
}
}
}
if (interfaces == null) {
interfaces = newClass<?>[]{invoker.getInterface(), EchoService.class};
}
return getProxy(invoker, interfaces);
}
最后的getProxy()方法在AbstractProxyFactory中是个抽象方法,实现的方法在子类JavassistProxyFactory中:
@SuppressWarnings("unchecked")
public <T> TgetProxy(Invoker<T> invoker, Class<?>[] interfaces) {
return (T)Proxy.getProxy(interfaces).newInstance(new InvokerInvocationHandler(invoker));
}
这里生成了代理类并创建了代理对象,可以在代码中引用,比如这样:
public class OrderController {
@Autowired
private OrderService orderService;
public void testDubboService() throws Exception{
orderService.selectByOrderId();
}
}