在xml上写一个dubbo标签就可以把远程的服务引用到本地使用:
<dubbo:service interface="com.test.dubbo.service.BuyFoodService" ref="buyFoodService"/>
既然用spring那就是Schema了,dubbo中自定义了Schema,在DubboNamespaceHandler中:
registerBeanDefinitionParser("service", new DubboBeanDefinitionParser(ServiceBean.class, true));
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()方法。
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,并没有判断,不是很好,如果没有构造函数需要抛出异常打印出友好的提示可能会好点。这里就是把JavassistProxyFactory生成好的proxy作为参数生成出装饰实例。如此在这个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容器中实际指向的是一个封装好的代理。
原文:http://www.cnblogs.com/killbug/p/7531113.html