在xml上寫一個dubbo標籤就能夠把遠程的服務引用到本地使用:html
<dubbo:reference id="buyFoodService" interface="com.test.dubbo.service.BuyFoodService"/>
既然用spring那就是Schema了,dubbo中自定義了Schema,在DubboNamespaceHandler中:java
registerBeanDefinitionParser("reference", new DubboBeanDefinitionParser(ReferenceBean.class, false));
public void init() { registerBeanDefinitionParser("application", new DubboBeanDefinitionParser(plicationConfig.class, true)); registerBeanDefinitionParser("module", new DubboBeanDefinitionParser(duleConfig.class, true)); registerBeanDefinitionParser("registry", new DubboBeanDefinitionParser(gistryConfig.class, true)); registerBeanDefinitionParser("monitor", new DubboBeanDefinitionParser(nitorConfig.class, true)); registerBeanDefinitionParser("provider", new DubboBeanDefinitionParser(oviderConfig.class, true)); registerBeanDefinitionParser("consumer", new DubboBeanDefinitionParser(nsumerConfig.class, true)); registerBeanDefinitionParser("protocol", new DubboBeanDefinitionParser(otocolConfig.class, true)); registerBeanDefinitionParser("service", new DubboBeanDefinitionParser(rviceBean.class, true)); registerBeanDefinitionParser("reference", new DubboBeanDefinitionParser(ferenceBean.class, false)); registerBeanDefinitionParser("annotation", new DubboBeanDefinitionParser(notationBean.class, true)); }
Boolean b = isInit(); if (b == null && getConsumer() != null) { b = getConsumer().isInit(); } if (b != null && b.booleanValue()) { getObject(); }
這個init就是前面設置reference標籤時的一個可選屬性,若是咱們設置true,那麼在執行afterPropertiesSet()的時候就會執行到這個getObject()方法。spring
public Object getObject() throws Exception { return get(); }
public synchronized T get() { if (destroyed) { throw new IllegalStateException("Already destroyed!"); } if (ref == null) { init(); } return ref; }
private static final ProxyFactory proxyFactory = ExtensionLoader.getExtensionLoader(ProxyFactory.class).getAdaptiveExtension(); private static final Protocol refprotocol = ExtensionLoader.getExtensionLoader(Protocol.class).getAdaptiveExtension();
ProxyFactory的代碼:
@SPI("javassist") public interface ProxyFactory { @Adaptive({Constants.PROXY_KEY}) <T> T getProxy(Invoker<T> invoker) throws RpcException; @Adaptive({Constants.PROXY_KEY}) <T> Invoker<T> getInvoker(T proxy, Class<T> type, URL url) throws RpcException; }
Protocol的代碼:
@SPI("dubbo") public interface Protocol { @Adaptive <T> Exporter<T> export(Invoker<T> invoker) throws RpcException; @Adaptive <T> Invoker<T> refer(Class<T> type, URL url) throws RpcException; void destroy(); }
public <T> T getProxy(Invoker<T> invoker) throws RpcException { T proxy = proxyFactory.getProxy(invoker); if (GenericService.class != invoker.getInterface()) { // 查看有沒有stub屬性 String stub = invoker.getUrl().getParameter(Constants.STUB_KEY, invoker.getUrl().getParameter(Constants.LOCAL_KEY)); if (ConfigUtils.isNotEmpty(stub)) { Class<?> serviceType = invoker.getInterface(); if (ConfigUtils.isDefault(stub)) { if (invoker.getUrl().hasParameter(Constants.STUB_KEY)) { stub = serviceType.getName() + "Stub"; } else { stub = serviceType.getName() + "Local"; } } try { Class<?> stubClass = ReflectUtils.forName(stub); if (! serviceType.isAssignableFrom(stubClass)) { throw new IllegalStateException("The stub implemention class " + stubClass.getName() + " not implement interface " + serviceType.getName()); } try { // 判斷有沒有參數是本service的構造函數,要有這個函數才能可用 Constructor<?> constructor = ReflectUtils.findConstructor(stubClass, serviceType); // 這裏看到是直接使用constructor,並無判斷,不是很好,看起來有問題,實際在解析stub屬性的時候已經作過是否包含指定構造函數,若是沒有責會報錯。因此這裏能夠放心使用,不會空指針。 proxy = (T) constructor.newInstance(new Object[] {proxy}); //export stub service URL url = invoker.getUrl(); if (url.getParameter(Constants.STUB_EVENT_KEY, Constants.DEFAULT_STUB_EVENT)){ url = url.addParameter(Constants.STUB_EVENT_METHODS_KEY, StringUtils.join(Wrapper.getWrapper(proxy.getClass()).getDeclaredMethodNames(), ",")); url = url.addParameter(Constants.IS_SERVER_KEY, Boolean.FALSE.toString()); try{ export(proxy, (Class)invoker.getInterface(), url); }catch (Exception e) { LOGGER.error("export a stub service error.", e); } } } catch (NoSuchMethodException e) { throw new IllegalStateException("No such constructor \"public " + stubClass.getSimpleName() + "(" + serviceType.getName() + ")\" in stub implemention class " + stubClass.getName(), e); } } catch (Throwable t) { LOGGER.error("Failed to create stub implemention class " + stub + " in consumer " + NetUtils.getLocalHost() + " use dubbo version " + Version.getVersion() + ", cause: " + t.getMessage(), t); // ignore } } } return proxy; }
返回代理實例,因此在開頭申明的BuyFoodService,在spring容器中實際指向的是一個封裝好的代理。緩存