SOFA源码学习

这里源码主要学习服务的发布和引用

为什么要有服务的发布和引用

  • Sofa中不同模块之间的spring context上下文是相互隔离的
  • 两个模块之间的bean不能通过spring的依赖注入来直接调用
  • Sofa通过将bean注册为服务,进行发布和引用,用来解决不同模块之间调用的问题。
  • JVM 服务发布和引用:解决一个 SOFA 应用内部不同模块之间的调用问题(单机调用)
  • RPC 服务发布和引用:解决多个 SOFA 应用之间不同模块的调用问题(跨机调用)

基本功能

VM服务发布和引用

用于同一个Sofa应用不同模块之间服务的相互调用,有XML配置和注解两个方式

1.XML配置

服务发布

  • 创建接口和实现类:
public interface JvmService(){
    String get();
}
public Class JvmServiceImpl extend JvmService(){
    @Overrride
    public String get(){
        return "Jvm";
    }
}
  • 在Spring xml配置文件中,将实现类声明为一个bean
<bean id="jvmService" class="cn.test.impl.JvmServiceImpl"/>
  • 将bean注册为sofa服务,本工程中的其他模块就可以引用了。
<sofa:service ref="jvmService" interface="cn.test.JvmService"/>

服务引用

  • 在Spring xml配置文件中,引用上述发布出来的sofa服务
<sofa:reference id="jvmService" interface="cn.test.JvmService"/>
  • 代码中直接用Spring注解@Autowired自动注入就可以使用
@Autowired
private JvmService jvmService;

2.注解

服务发布

  • 创建接口和实现类,接口一样,实现类上打上@SofaService注解
@SofaService
public class JvmServiceImpl implements JvmService {
    @Override
    public String get() {
        return "JVM";
    }
}
  • 将实现类注册为Spring Bean,和上面一样

服务引用

  • 使用的时候,直接使用@SofaReference注解,运行的时候会将上面注册的sofa服务注入到此处的变量中。
@SofaReference
private JvmService jvmService;

RPC服务发布和引用

用于跨机调用不同Sofa应用之间服务的发布和引用,目前只支持XML配置方式

服务发布

  • 创建接口和实现类RpcService和RpcServiceImpl,和以上JVM服务一样
  • 使用XML的方式,在Spring xml配置文件中将实现类注册成为RPC服务(只能通过XML的方式配置,不能使用注解)
<sofa:service ref="rpcService " interface="cn.test.RpcService">
        <sofa:binding.tr/><!-- 加上这句,表示这个服务被注册为基于taobao remoteing的RPC服务 -->
</sofa:service>

服务引用

  • 在Spring xml配置文件中,将RPC服务引入过来
<sofa:reference id="rpcService" interface="cn.test.RpcService">
    <sofa:binding.tr/><!-- 加上这句,表示要引入的这个服务是基于taobao remoteing的RPC服务 -->
</sofa:reference>
  • 代码中直接用Spring注解@Autowired自动注入就可以使用
@Autowired
private RpcService rpcService;

使用总结

  • @SofaService和@SofaReference只能在JVM服务发布和引用中使用,RPC服务的发布和引用必须采用XML的方式进行配置
  • 因此平时尽量采用XML的方式进行服务的发布和引用,RPC服务就是在JVM的基础之上,增加<sofa:binding.tr/>即可。

源码分析

sofa4源代码地址:http://gitlab.alipay-inc.com/jiuzhou-middleware/sofa4
sofa-rpc源代码地址:http://gitlab.alipay-inc.com/jiuzhou-middleware/sofa-rpc

服务发布和引用

标签解析:生成bean

1.在xml中引入sofa命名空间

// sofa命名空间
xmlns:sofa="http://schema.alipay.com/sofa/schema/service"
// 该命名空间的唯一标示
xsi:schemaLocation="http://schema.alipay.com/sofa/schema/service
http://schema.alipay.com/sofa/sofa-service-4-0-0.xsd"

2.通知Spring加载sofa标签

sofa标签是通过Spring来进行解析和加载的,我们需要做的是告诉Spring如何解析这个标签,通知Spring的方式就是通过spring.schemas和spring.handlers两个文件来完成的。在sofa-runtime-service-x.x.x.jar这个jar包下的META-INF中定义了这两个文件:

http\://schema.alipay.com/sofa/common/sofa-service-4-0-0.xsd=com/alipay/sofa/service/config/common/sofa-service.xsd
http\://schema.alipay.com/sofa/schema/service=com.alipay.sofa.runtime.spring.SofaNamespaceHandler

可以看出,sofa:service和sofa:reference标签的解析是通过com.alipay.sofa.runtime.spring.SofaNamespaceHandler这个类来完成的(实际上这个类并没有进行解析,只是为相应标签注册解析器)。

3.解析sofa:service和sofa:reference标签

可以看出,SofaNamespaceHandler首先获得这个appname下的所有BeanDefinitionParser,将其注册到spring中,然后这些BeanDefinitionParser会根据不同的tagName对其进行解析。

public class SofaNamespaceHandler extends NamespaceHandlerSupport {
    ...//
    public void init() {
        registerBeanDefinitionParsers();
        registerBeanDefinitionDecorators();
    }
    private void registerBeanDefinitionParsers() {
        BeanDefinitionParserRegistry beanDefinitionParserRegistry = SofaFrameworkHolder.injector
            .getInstance(PluginServiceManager.class).getBeanDefinitionParserRegistry(appName);
        Set<BeanDefinitionParser> beanDefinitionParsers = beanDefinitionParserRegistry
            .getBeanDefinitionParsers();
        if (beanDefinitionParsers == null) {
            return;
        }
        for (BeanDefinitionParser beanDefinitionParser : beanDefinitionParsers) {
            if (!(beanDefinitionParser instanceof TagNameSupport)) {
                continue;
            }
            String tagName = ((TagNameSupport) beanDefinitionParser).supportTagName();
            registerBeanDefinitionParser(tagName, beanDefinitionParser);
        }
    }
}
  • 服务发布的标签解析器
    服务发布的标签是<sofa:service...>,也就是tagName是service,对应的解析器是由ServiceDefinitionParser这个类完成的。解析的结果是一个对应的springbean,也就是getBeanClass方法的返回值,这里是ServiceFactoryBean。
package com.alipay.sofa.runtime.service.spring;
public class ServiceDefinitionParser extends AbstractContractDefinitionParser {
    private static final String                  REF      = "ref";
    private static final String                  BEAN_ID  = "beanId";
    private static final ServiceDefinitionParser instance = new ServiceDefinitionParser();

    private ServiceDefinitionParser() { }
    public static ServiceDefinitionParser getInstance() { return instance;}
    @Override
    protected void doParseInternal(Element element, ParserContext parserContext,
                                   BeanDefinitionBuilder builder) {
        String ref = element.getAttribute(REF);
        builder.addPropertyReference(REF, ref);
        builder.addPropertyValue(BEAN_ID, ref);
    }
    @Override
    protected Class getBeanClass(Element element) {
        return ServiceFactoryBean.class;
    }
    // 配置 <sofa:service> 的时候是不需要配置 id 属性的,所以我们必须给生成一个
    @Override
    protected boolean shouldGenerateIdAsFallback() { return true;}
    @Override
    public String supportTagName() { return "service";}
}
  • 服务引用的标签解析器
    服务引用的标签解析是由类ReferenceDefinitionParser完成的,解析的结果是ReferenceFactoryBean。
package com.alipay.sofa.runtime.service.spring;
public class ReferenceDefinitionParser extends AbstractContractDefinitionParser {
    ...//
    @Override
    protected Class getBeanClass(Element element) {
        return ReferenceFactoryBean.class;
    }
    @Override
    public String supportTagName() {
        return "reference";
    }
}

服务发布:生成&注册组件

服务发布解析结果是生成ServiceFactoryBean,这是一个工厂类,根据getObject方法来生成service对象实例,对象生成时会触发doAfterPropertiesSet进行初始化,生成一个sofa服务组件对象componentInfo,并通过register方法将组件注册到sofa上下文sofaRuntimeContext中。

package com.alipay.sofa.runtime.service.spring;
public class ServiceFactoryBean extends AbstractContractFactoryBean {
    protected Object  ref;
    protected String  beanId;
    protected Service service;

    @Override
    protected void doAfterPropertiesSet() throws Exception {
        // Issue #62 判断 Bean 的实现类上是否有 @SofaService 的注解
        if (hasSofaServiceAnnotation()) {
            throw new ServiceRuntimeException(
                "Bean " + beanId + " of type " + ref.getClass()
                        + " has already annotated by @SofaService,"
                        + " can not be registered using xml. Please check it.");
        }
        Implementation implementation = new DefaultImplementation();
        implementation.setTarget(ref);
        service = buildService();
        if (bindings.size() == 0) { bindings.add(new JvmBinding());}
        for (Binding binding : bindings) { service.addBinding(binding);}

        ComponentInfo componentInfo = new ServiceComponent(implementation, service,
            sofaRuntimeContext);
        sofaRuntimeContext.getComponentManager().register(componentInfo);
    }
    ...//
    @Override
    public Object getObject() throws Exception {
        return service;
    }
    ...//
}

查看ComponentManager的register方法实现,可以看到依次调用服务组件的register(),resolve(),activate()三个方法,把组件对象塞到全局的registry中,程序运行中,所有模块都可以通过registry获得想要的服务。

public class ComponentManagerImpl implements ComponentManager {
    @Override
    public synchronized void register(ComponentInfo componentInfo) {
        _register(componentInfo);
    }
    private ComponentInfo _register(ComponentInfo ci) {
        ComponentName name = ci.getName();
        if (isRegistered(name)) {
            LOGGER.error("Component was already registered: " + name);
            return getComponentInfo(name);
        }
        try {
            ci.register();
        } catch (Exception e) {
            LOGGER.error("Failed to register component: " + ci.getName(), e);
            return null;
        }
        LOGGER.info("Registering component: " + ci.getName());
        try {
            registry.put(ci.getName(), ci);
            if (ci.resolve()) {
                // 组册到类型容器中
                _typeRegistry(ci);
                boolean isLazyActivate;
                if (ci instanceof AbstractComponent) {
                    isLazyActivate = ((AbstractComponent) ci).isLazyActivateInternal();
                } else {
                    isLazyActivate = ci.isLazyActivate();
                }
                if (!isLazyActivate) {
                    ci.activate();
                } else {
                    lazyComponents.put(ci.getName(), ci);
                }
            }
        } catch (Exception e) {
            ci.exception(e);
            LOGGER.error("Failed to create the component " + ci.getName(), e);
        }
        return ci;
    }
}

查看register(),resolve(),active()三个方法的实现,可以看出register和resolve两个方法只是简单的改变一下组件的状态

UNREGISTERED(0, "撤销注册"), REGISTERED(0, "已注册"), RESOLVED(0, "已解析"), ACTIVATED(0, "已激活");
public abstract class AbstractComponent implements ComponentInfo {
    @Override
    public void register() {
        if (componentStatus != ComponentStatus.UNREGISTERED) {
            return;
        }
        componentStatus = ComponentStatus.REGISTERED;
    }

    @Override
    public boolean resolve() {
        if (componentStatus != ComponentStatus.REGISTERED) {
            return false;
        }
        componentStatus = ComponentStatus.RESOLVED;
        return true;
    }

    @Override
    public void activate() throws ServiceRuntimeException {
        if (componentStatus != ComponentStatus.RESOLVED) {
            return;
        }
        if (!checkImplementation()) {
            return;
        }
        Object target = this.implementation.getTarget();
        if (target instanceof ComponentLifeCycle) {
            ((ComponentLifeCycle) target).activate();
        } else {
            invokeWithArgs("activate");
        }
        componentStatus = ComponentStatus.ACTIVATED;
    }
}

ServiceComponent重写的active方法如下,可以看到activate会获取到服务的 Binding 集,然后迭代加载每一个 Binding 对应 BindingAdapter,再调用 outBinding 对外暴露服务。

public class ServiceComponent extends AbstractComponent {
    @Override
    public void activate() throws ServiceRuntimeException {
        activateBinding();
        super.activate();
    }

    private void activateBinding() {
        Object target = service.getTarget();
        if (target == null) {
            throw new ServiceRuntimeException(
                "Must contains the target object whiling registering Service.");
        }
        // 存在绑定。
        if (service.hasBinding()) {
            Set<Binding> bindings = service.getBindings();
            Iterator<Binding> it = bindings.iterator();
            boolean allPassed = true;
            while (it.hasNext()) {
                Binding binding = it.next();
                BindingAdapter<Binding> bindingAdapter = this.bindingAdapterManager.loadAdapter(binding.getBindingType());
                if (bindingAdapter == null) {
                    ...//异常
                }
                Object outBindingResult;
                SofaLogger.BINDING_LOG.info(" <<Out Binding [" + binding.getBindingType() + "] Begins - " + service);
                try {
                    outBindingResult = bindingAdapter.outBinding(service, binding, target, getContext());
                } catch (Throwable t) {
                    allPassed = false;
                    SofaLogger.BINDING_LOG.error(" <<Out binding [" + binding.getBindingType() + "] for [" + service + "] occur exception, ", t);
                    continue;
                }
                if (outBindingResult != null && !Boolean.FALSE.equals(outBindingResult)) {
                    SofaLogger.BINDING_LOG.info(" <<Out Binding [" + binding.getBindingType() + "] Ends - " + service);
                } else {
                    binding.setHealthy(false);
                    SofaLogger.BINDING_LOG.info(" <<Out Binding [" + binding.getBindingType() + "] Fails, Don't publish service - " + service);
                }
            }
        }
        SofaLogger.BINDING_LOG.info("Register Service - " + service);
    }
}

JVM服务的Adater是JvmBindingAdapter,对于JVM服务来说是内部调用不需要暴露给外部,因此JVM服务的outBinding返回的是null,同一应用下其他模块调用该服务直接查本地注册中心registry即可。

public class JvmBindingAdapter implements BindingAdapter<JvmBinding> {
    @Override
    public Object outBinding(Object contract, JvmBinding binding, Object target,
                             SofaRuntimeContext sofaRuntimeContext) {
        return null;
    }
}

Rpc服务的Adapter是RpcBindingAdapter,对于RPC服务需要暴露给外部,因此RpcBindingAdapter的outBinding方法中会将服务推送到远程注册中心中。这样其他应用就可以通过注册中心调用该服务。

public abstract class RpcBindingAdapter<T extends RpcBinding> implements BindingAdapter<T> {
    @Override
    public Object outBinding(Object contract, T binding, Object target,
                             SofaRuntimeContext sofaRuntimeContext) {
        if (!judgeBinding(contract, binding, target, sofaRuntimeContext)) {
            return Boolean.FALSE;
        }
        String uniqueName = getUniqueName((Contract) contract);
        ServiceMetadata metadata = getServiceMetadata(uniqueName);
        if (metadata == null) {
            if (notNeedPublishServiceSet.contains(uniqueName)) {
                return Boolean.FALSE;
            } else {
                throw new ServiceRuntimeException(LogCodes.getLog(LogCodes.INFO_SERVICE_METADATA_IS_NULL, uniqueName));
            }
        }
        try {
            // 将服务推送到远程注册中心
            this.getProcessService().provide(metadata);
        } catch (Exception e) {
            throw new ServiceRuntimeException(LogCodes.getLog(LogCodes.ERROR_PROXY_PUBLISH_FAIL), e);
        }
        return Boolean.TRUE;
    }
}

服务引用:找到&注册组件

标签解析的结果是生成ReferenceFactoryBean,Reference的目标就是把sofa runtime context的一个组件变成spring中的一个bean,核心代码在于proxy = ReferenceRegisterHelper.registerReference(reference, sofaRuntimeContext,applicationContext);这一句,这句代码会从SOFA上下文中,拿到服务对应的代理对象。getObject方法会会返回该对象proxy。

package com.alipay.sofa.runtime.spring.factory;
public class ReferenceFactoryBean extends AbstractContractFactoryBean {
    private Object    proxy;
    protected boolean localFirst = true;
    protected boolean jvmService;

    @Override
    protected void doAfterPropertiesSet() throws Exception {
        Reference reference = buildReference();
        Assert
            .isTrue(bindings.size() <= 1,
                "Found more than one binding in <sofa:reference/>, <sofa:reference/> can only have one binding.");
        if (bindings.size() == 0) {
            bindings.add(new JvmBinding());
        }
        reference.addBinding(bindings.get(0));
        proxy = ReferenceRegisterHelper.registerReference(reference, sofaRuntimeContext);
    }

    @Override
    public Object getObject() throws Exception {
        return proxy;
    }
}

深入看到registerReference方法来看它是如何拿到服务对应的对象的。主要做了两个事:

  1. 给RPC服务引用自动增加一个JVM绑定,也就是一个RPC服务默认会有JVM和RPC两个binding,以达到优先本地JVM调用
  2. sofa的componentManager将该reference注册成一个组件,注册之后生成引用服务的代理对象。
package com.alipay.sofa.runtime.service.helper;
public class ReferenceRegisterHelper {
    public static Object registerReference(Reference reference,
                                           SofaRuntimeContext sofaRuntimeContext) {
        Binding binding = (Binding) reference.getBindings().toArray()[0];
        if (reference.jvmService() && binding.getBindingType().equals(JvmBinding.JVM_BINDING_TYPE)) {
            throw new ServiceRuntimeException(
                "jvm-service=\"true\" can not be used with JVM binding.");
        }
        // 优先本地调用
        if (!binding.getBindingType().equals(JvmBinding.JVM_BINDING_TYPE)
            && isLocalFirst(reference, sofaRuntimeContext)) {
            reference.addBinding(new JvmBinding());
        }
        ComponentManager componentManager = sofaRuntimeContext.getComponentManager();
        ReferenceComponent referenceComponent = new ReferenceComponent(reference,
            new DefaultImplementation(), sofaRuntimeContext);
        // 保证若不存在,则注册为原子操作
        // 去掉此处 ReferenceRegisterHelper 的锁,此处的锁不需要,ComponentManager 中已带锁,背景见 http://gitlab.alipay-inc.com/jiuzhou-middleware/sofa4/issues/257
        // 如果component已注册,返回已注册的component
        if (componentManager.isRegistered(referenceComponent.getName())) {
            return componentManager.getComponentInfo(referenceComponent.getName())
                .getImplementation().getTarget();
        }
        ComponentInfo componentInfo = componentManager.registerAndGet(referenceComponent);
        return componentInfo.getImplementation().getTarget();
    }
}

再查看ComponentManager的registerAndGet方法,可以看到也是调用了之间注册组件的_register方法。register() -> resolve() -> activate() ,其中register和resolve也只是改变状态,代理对象的生成在active方法中完成。

public class ComponentManagerImpl implements ComponentManager {
    @Override
    public void register(ComponentInfo componentInfo) {
        _register(componentInfo);
    }
}

引用组件ReferenceComponent的active实现如下,代理对象的生成与binding有很大关系,不同类型的binding会生成不同类型的代理对象(JVM和RPC)。如果reference上只有一个binding,这只要使用这个binding生成代理对象即可;如果有多个binding,则优先使用jvm binding来生成本地调用的代理对象,其他类型的binding生成的远程调用的代理对象作为jvm binding生成的对象的备选,这样做也是为了优先本地调用,如果本地代理对象不存在,则会使用远程代理对象。

public class ReferenceComponent extends AbstractComponent {
    @Override
    public void activate() throws ServiceRuntimeException {
        if (reference.hasBinding()) {
            Binding candidate = null;
            Set<Binding> bindings = reference.getBindings();
            // 如果binding个数大于1,说明设置了jvm优先调用
            if (bindings.size() == 1) {
                candidate = bindings.iterator().next();
            } else if (bindings.size() > 1) {
                // 有多个说明设置了local-first=true,要求本地调用优先
                Object backupProxy = null;
                for (Binding binding : bindings) {
                    if ("jvm".equals(binding.getName())) {
                        candidate = binding;
                    } else {
                        backupProxy = createProxy(reference, binding);
                    }
                }
                if (candidate != null) {
                    // 一般不会出现 candidate 为 null 的情况,一个 Reference 的绑定,至少会有一个 JVM 绑定
                    ((JvmBinding) candidate).setBackupProxy(backupProxy);
                }
            }
            Object proxy = null;
            // 生成代理对象
            if (candidate != null) {
                proxy = createProxy(reference, candidate);
            }
            if (proxy != null) {
                try {
                    // Spring xml 引用服务, 具体参考 http://gitlab.alipay-inc.com/alipay-sofa/sofa-dynamic-module-runtime/issues/6
                    // 这里直接 new 空的 ApplicationContext 单纯为了兼容 XTS 使用的老接口
                    InterfaceMode interfaceMode = reference.getInterfaceMode();
                    if (interfaceMode.equals(InterfaceMode.spring)) {
                        proxy = postProcessReferenceProxy(reference, proxy,
                            new GenericApplicationContext());
                    } else {
                        proxy = postProcessReferenceProxy(reference, proxy, null);
                    }
                } catch (Throwable e) {
                    SofaLogger.BINDING_LOG.error(
                        "Failed to invoke post process reference, use origin proxy instead.", e);
                }
            }
            this.implementation = new DefaultImplementation();
            implementation.setTarget(proxy);
        }
        publishAsService(reference, implementation.getTarget());
        super.activate();
        latch.countDown();
    }
}

那么,如何通过binding来生成代理对象呢?就是通过createProxy中调用不同bindingAdapter的inBinding方法,借助于动态代理技术进行生成。

private Object createProxy(Reference reference, Binding binding) {
    BindingAdapter<Binding> bindingAdapter = this.bindingAdapterManager.loadAdapter(binding
        .getBindingType());
    if (bindingAdapter == null) {
        ...// 异常
    }
    SofaLogger.BINDING_LOG.info(" >>In Binding [" + binding.getBindingType() + "] Begins - " + reference);
    Object proxy = null;
    try {
        proxy = bindingAdapter.inBinding(reference, binding, sofaRuntimeContext);
    } finally {
        SofaLogger.BINDING_LOG.info(" >>In Binding [" + binding.getBindingType() + "] Ends - " + reference);
    }
    return proxy;
}
  • JVM的binding,会使用JvmBindingAdapter来生成代理对象,生成的代理对象的InvocationHandler为JvmServiceInvoker。当调用代理对象的方法时,就会触发JvmServiceInvoker的doInvoke,内部会找到代理对象对应的目标对象进行调用。
public class JvmBindingAdapter implements BindingAdapter<JvmBinding> {
    public Object inBinding(Object contract, JvmBinding binding,
                            SofaRuntimeContext sofaRuntimeContext) {
        return createServiceProxy((Contract) contract, binding, sofaRuntimeContext);
    }
    protected Object createServiceProxy(Contract contract, JvmBinding binding,
                                        SofaRuntimeContext sofaRuntimeContext) {
        ...//
        ClassLoader oldClassLoader = Thread.currentThread().getContextClassLoader();
        try {
            Thread.currentThread().setContextClassLoader(newClassLoader);
            // 生成代理对象
            ServiceProxy handler = new JvmServiceInvoker(contract, binding, sofaRuntimeContext);
            ...
        }
    }
}
  • RPC的binding,会调用RpcBindingAdapter来生成代理对象,生成代理对象的Handler为SofaServiceProxy。当调用代理对象的方法时,就会触发SofaServiceProxy的doInvoke,进而发起RPC调用

总结图

image

总结

解析

  • 对标签注册相应解析器:com.alipay.sofa.runtime.spring.SofaNamespaceHandler
    (绑定tagName和beanDefinitionParser )
  • 对相应标签进行解析
    • <sofa:service>:com.alipay.sofa.runtime.spring.parser.ServiceDefinitionParser
    • <sofa:reference>:com.alipay.sofa.runtime.spring.parser.ReferenceDefinitionParser
  • 标签解析过程
    • 父类AbstractContractDefinitionParser的doParse方法:解析service和reference的共有属性
    • 对应parser自身的doParseInternal方法:解析私有熟悉
  • 标签解析结果
    • <sofa:service>:com.alipay.sofa.runtime.spring.factory.ServiceFactoryBean
    • <sofa:reference>:com.alipay.sofa.runtime.spring.factory.ReferenceFactoryBean

生成组件

  • 服务发布组件ServiceComponent:在ServiceFactoryBean的doAfterPropertiesSet中生成并注册组件

  • 服务引用组件ReferenceComponent:在ReferenceFactoryBean的doAfterPropertiesSet中生成并注册组件

服务发布注册组件

  • 目的:将服务的bean注册到Sofa Runtime Context中

  • 服务组件管理接口:ComponentManager

  • 注册中心:registry(componentManager的一个实例)

  • 注册组件经历三个过程:register(),resolve(),activate()

  • activate() 获取到服务的Binding集,加载每一个Binding对应BindingAdapter,调用outBinding对外暴露服务

    • JVM服务发布的Adapter:JvmBindingAdapter,outBinding返回null(不需要暴露)

    • RPC服务发布的Adapter:RpcBindingAdapter,将服务注册到注册中心。

服务引用注册组件

  • 目的:将Sofa Runtime Context的一个服务注册成spring的一个bean

  • 拿到服务对应的对象:ReferenceRegisterHelper的registerReference

    • 给RPC服务引用自动增加一个JVM绑定,以达到优先本地JVM调

    • 调用componentManager的registerAndGet方法注册并生成引用服务的代理对象

  • 生成代理对象:ReferenceComponent的active方法

    • 如果有多个binding,优先使用jvm binding来生成本地调用的代理对象

    • JvmBindingAdapter生成代理对象的handler:JvmServiceInvoker

    • RpcBindingAdapter生成代理对象的handler:SofaServiceProxy

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,219评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,363评论 1 293
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,933评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,020评论 0 206
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,400评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,640评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,896评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,597评论 0 199
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,327评论 1 244
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,581评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,072评论 1 261
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,399评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,054评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,083评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,849评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,672评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,585评论 2 270

推荐阅读更多精彩内容