Dubbo-服務消費者初始化


服務消費者初始化過程,即生成RefrenceBean的過程 
 
整體執行流程
備注: Dubbo 默認使用 Javassist 框架為服務接口生成動態代理類可以使用使用阿里開源 Java 應用診斷工具 Arthas 反編譯代理類
 
Dubbo官網提供的時序圖
 
 
一、RefrenceBean生成過程
RefrenceBean是一個FactoryBean
spring容器在啟動過程中執行
(1)bean定義注冊
客戶端在啟動的過程中會注冊4種類型的bean定義
  • com.alibaba.dubbo.config.RegistryConfig(注冊中心相關)
  • com.alibaba.dubbo.config.ProviderConfig(服務提供者相關)
  • demoService
  • demo-consumer
(2)單例非懶加載bean的創建
  1. 以demoService的bean創建為例,demoService屬於ReferenceBean類型的工廠bean
  2. demoService在實例化后(earlySingletonExposure為true提前暴露)准備開始進行屬性注入,即將其所有暴露的method作為屬性;
  3. demoService將demoService.sayHello方法當成它的屬性,並始對它進行屬性注入(emoService.sayHello是一個Method類型的bean);
  4. 開始創建名為demoService.sayHello的bean,這個Bean屬於MethodConfig;
 
二、代理bean生成過程
當執行context.getBean("demoService") 方法時
protected <T> T doGetBean(
    final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)
    throws BeansException {

    final String beanName = transformedBeanName(name);
    Object bean;

    // Eagerly check singleton cache for manually registered singletons.
    // spring容器在啟動完成后FactoryBean就已經創建好了,demoService屬於ReferenceBean工廠bean
    Object sharedInstance = getSingleton(beanName);
    if (sharedInstance != null && args == null) {
        if (logger.isDebugEnabled()) {
            if (isSingletonCurrentlyInCreation(beanName)) {
                logger.debug("Returning eagerly cached instance of singleton bean '" + beanName +
                             "' that is not fully initialized yet - a consequence of a circular reference");
            }
            else {
                logger.debug("Returning cached instance of singleton bean '" + beanName + "'");
            }
        }
        // 關鍵代碼 sharedInstance為ReferenceBean
        bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
    }
    // 省略若干代碼...
}

 

從FactoryBean獲取對象
protected Object getObjectForBeanInstance(
    Object beanInstance, String name, String beanName, RootBeanDefinition mbd) {

    // Don't let calling code try to dereference the factory if the bean isn't a factory.
    if (BeanFactoryUtils.isFactoryDereference(name) && !(beanInstance instanceof FactoryBean)) {
        throw new BeanIsNotAFactoryException(transformedBeanName(name), beanInstance.getClass());
    }

    // Now we have the bean instance, which may be a normal bean or a FactoryBean.
    // If it's a FactoryBean, we use it to create a bean instance, unless the
    // caller actually wants a reference to the factory.
    if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) {
        return beanInstance;
    }

    Object object = null;
    if (mbd == null) {
        // 第一次執行時,取出的結果為null
        object = getCachedObjectForFactoryBean(beanName);
    }
    if (object == null) {
        // Return bean instance from factory.
        FactoryBean<?> factory = (FactoryBean<?>) beanInstance;
        // Caches object obtained from FactoryBean if it is a singleton.
        if (mbd == null && containsBeanDefinition(beanName)) {
            mbd = getMergedLocalBeanDefinition(beanName);
        }
        boolean synthetic = (mbd != null && mbd.isSynthetic());
        // 關鍵代碼
        object = getObjectFromFactoryBean(factory, beanName, !synthetic);
    }
    return object;
}

 

protected Object getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess) {
    if (factory.isSingleton() && containsSingleton(beanName)) {
        synchronized (getSingletonMutex()) {
            Object object = this.factoryBeanObjectCache.get(beanName);
            if (object == null) {
                // 關鍵代碼...
                object = doGetObjectFromFactoryBean(factory, beanName);
                // Only post-process and store if not put there already during getObject() call above
                // (e.g. because of circular reference processing triggered by custom getBean calls)
                Object alreadyThere = this.factoryBeanObjectCache.get(beanName);
                if (alreadyThere != null) {
                    object = alreadyThere;
                }
                else {
                    if (object != null && shouldPostProcess) {
                        try {
                            object = postProcessObjectFromFactoryBean(object, beanName);
                        }
                        catch (Throwable ex) {
                            throw new BeanCreationException(beanName,
                                                            "Post-processing of FactoryBean's singleton object failed", ex);
                        }
                    }
                    this.factoryBeanObjectCache.put(beanName, (object != null ? object : NULL_OBJECT));
                }
            }
            return (object != NULL_OBJECT ? object : null);
        }
    }
    else {
        // 關鍵代碼...
        Object object = doGetObjectFromFactoryBean(factory, beanName);
        if (object != null && shouldPostProcess) {
            try {
                object = postProcessObjectFromFactoryBean(object, beanName);
            }
            catch (Throwable ex) {
                throw new BeanCreationException(beanName, "Post-processing of FactoryBean's object failed", ex);
            }
        }
        return object;
    }
}

 

private Object doGetObjectFromFactoryBean(final FactoryBean<?> factory, final String beanName)
    throws BeanCreationException {

    Object object;
    try {
        if (System.getSecurityManager() != null) {
            AccessControlContext acc = getAccessControlContext();
            try {
                object = AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
                    @Override
                    public Object run() throws Exception {
                        return factory.getObject();
                    }
                }, acc);
            }
            catch (PrivilegedActionException pae) {
                throw pae.getException();
            }
        }
        else {
            // 核心方法,這個factory為ReferenceBean,因此直接調用ReferenceBean中getObject方法
            object = factory.getObject();
        }
    }
    
    // 省略若干代碼...
    return object;
}

 

ReferenceBean 是一個FactoryBean,而FactoryBean中有三個重要的方法,其中一個就是getObject()
public Object getObject() throws Exception {
    return get();
}

 

ReferenceConfig 中的get 方法
public synchronized T get() {
    if (destroyed) {
        throw new IllegalStateException("Already destroyed!");
    }
    if (ref == null) {
        // 關鍵,所以這時間稍長一點的話,得到的結果為null
        init();
    }
    return ref;
}

上面采用非阻塞異步的方式

 
ReferenceConfig 中的init 方法
private void init() {
    // 省略若干代碼...
  
    StaticContext.getSystemContext().putAll(attributes);
    // 核心方法
    ref = createProxy(map);
}

 

private transient volatile Invoker<?> invoker;

private T createProxy(Map<String, String> map) {
    // 省略若干代碼...
    if (isJvmRefer) {
        URL url = new URL(Constants.LOCAL_PROTOCOL, NetUtils.LOCALHOST, 0, interfaceClass.getName()).addParameters(map);
        // 核心方法,拿到invoker對象        
        invoker = refprotocol.refer(interfaceClass, url);
    } else {
        // 省略若干代碼...
        if (urls.size() == 1) {
            // 核心方法,拿到invoker對象
            // refprotocol為Protocol$Adpative對象
            invoker = refprotocol.refer(interfaceClass, urls.get(0));
        } else {
            // 省略若干代碼...
        }
    }
    // 核心方法create service proxy 
    // 將下面這段代碼替換成 ProxyFactory$Adaptive 中 getProxy中的部分
    return (T) proxyFactory.getProxy(invoker); 
}

 

 
 
proxyFactory是一個ProxyFactory$Adaptive
invoker 是一個MockClusterInvoker對象
public class ProxyFactory$Adaptive implements ProxyFactory {
    public Object getProxy(Invoker invoker) throws RpcException {
        if (invoker == null) 
            throw new IllegalArgumentException("com.alibaba.dubbo.rpc.Invoker argument == null");
        if (invoker.getUrl() == null) 
            throw new IllegalArgumentException("com.alibaba.dubbo.rpc.Invoker argument getUrl() == null");
        com.alibaba.dubbo.common.URL url = invoker.getUrl();
        String extName = url.getParameter("proxy", "javassist");
        if(extName == null) 
            throw new IllegalStateException("Fail to get extension(ProxyFactory) name from url(" + url.toString() + ") use keys([proxy])");
        ProxyFactory extension = (ProxyFactory)ExtensionLoader.getExtensionLoader(ProxyFactory.class).getExtension(extName);
        return extension.getProxy(invoker);
    }
    public Invoker getInvoker(Object arg0, Class arg1, com.alibaba.dubbo.common.URL arg2) throws RpcException {
        if (arg2 == null) 
            throw new IllegalArgumentException("url == null");
        com.alibaba.dubbo.common.URL url = arg2;
        String extName = url.getParameter("proxy", "javassist");
        if(extName == null) 
            throw new IllegalStateException("Fail to get extension(ProxyFactory) name from url(" + url.toString() + ") use keys([proxy])");
        ProxyFactory extension = (ProxyFactory)ExtensionLoader.getExtensionLoader(ProxyFactory.class).getExtension(extName);
        return extension.getInvoker(arg0, arg1, arg2);
    } 
}

即:

// create service proxy
// 下面的代碼直接替換(T) proxyFactory.getProxy(invoker) 方法
com.alibaba.dubbo.common.URL url = invoker.getUrl();
String extName = url.getParameter("proxy", "javassist");    // extName為 javassist
ProxyFactory extension = (ProxyFactory)ExtensionLoader.getExtensionLoader(ProxyFactory.class).getExtension(extName);
// extension為StubProxyFactoryWrapper對象
// return (T) proxyFactory.getProxy(invoker);
return (T) extension.getProxy(invoker);

 

進入到StubProxyFactoryWrapper,再來分析一下getProxy 方法
public <T> T getProxy(Invoker<T> invoker) throws RpcException {
    T proxy = proxyFactory.getProxy(invoker);    // 關鍵部分...
    if (GenericService.class != invoker.getInterface()) {
       // 
    }
    return proxy;
}

上面 proxyFactory為JavassistProxyFactory類型,所以進入到JavassistProxyFactory類,分析一下它的getProxy方法

public <T> T getProxy(Invoker<T> invoker, Class<?>[] interfaces) {
    return (T) Proxy.getProxy(interfaces).newInstance(new InvokerInvocationHandler(invoker));
}

先來分析一下前面一部分的Proxy.getProxy(interfaces) 方法

public static Proxy getProxy(Class<?>... ics) {
    return getProxy(ClassHelper.getClassLoader(Proxy.class), ics);
}

這個方法特點長,但是非常重要

public static Proxy getProxy(ClassLoader cl, Class<?>... ics) {
    if (ics.length > 65535)
        throw new IllegalArgumentException("interface limit exceeded");

    // 省略了若干代碼
    // use interface class name list as key.
    String key = sb.toString();
    // key = com.alibaba.dubbo.demo.DemoService;com.alibaba.dubbo.rpc.service.EchoService;


    long id = PROXY_CLASS_COUNTER.getAndIncrement();
    String pkg = null;
    ClassGenerator ccp = null, ccm = null;
    try {
        ccp = ClassGenerator.newInstance(cl);

        Set<String> worked = new HashSet<String>();
        List<Method> methods = new ArrayList<Method>();

        for (int i = 0; i < ics.length; i++) {
            if (!Modifier.isPublic(ics[i].getModifiers())) {
                String npkg = ics[i].getPackage().getName();
                if (pkg == null) {
                    pkg = npkg;
                } else {
                    if (!pkg.equals(npkg))
                        throw new IllegalArgumentException("non-public interfaces from different packages");
                }
            }
            ccp.addInterface(ics[i]);
            // --------------------- 代理的關鍵部分 START ---------------
            // 
            for (Method method : ics[i].getMethods()) {
                String desc = ReflectUtils.getDesc(method);
                if (worked.contains(desc))
                    continue;
                worked.add(desc);

                int ix = methods.size();
                Class<?> rt = method.getReturnType();
                Class<?>[] pts = method.getParameterTypes();

                StringBuilder code = new StringBuilder("Object[] args = new Object[").append(pts.length).append("];");
                for (int j = 0; j < pts.length; j++)
                    code.append(" args[").append(j).append("] = ($w)$").append(j + 1).append(";");
                code.append(" Object ret = handler.invoke(this, methods[" + ix + "], args);");
                if (!Void.TYPE.equals(rt))
                    code.append(" return ").append(asArgument(rt, "ret")).append(";");

                methods.add(method);
                // 生成方法,就是給上面的字符串添加 方法名、方法返回類型及{、} 
                ccp.addMethod(method.getName(), method.getModifiers(), rt, pts, method.getExceptionTypes(), code.toString());
            }
            // --------------------- 代理的關鍵部分 START ---------------
        }

        if (pkg == null)
            pkg = PACKAGE_NAME;

        // create ProxyInstance class.
        String pcn = pkg + ".proxy" + id;    // 如生成com.alibaba.dubbo.common.bytecode.proxy0
        ccp.setClassName(pcn);
        ccp.addField("public static java.lang.reflect.Method[] methods;");
        ccp.addField("private " + InvocationHandler.class.getName() + " handler;");
        ccp.addConstructor(Modifier.PUBLIC, new Class<?>[]{InvocationHandler.class}, new Class<?>[0], "handler=$1;");
        ccp.addDefaultConstructor();
        Class<?> clazz = ccp.toClass();
        clazz.getField("methods").set(null, methods.toArray(new Method[0]));

        // create Proxy class.
        String fcn = Proxy.class.getName() + id;
        ccm = ClassGenerator.newInstance(cl);
        ccm.setClassName(fcn);
        ccm.addDefaultConstructor();
        ccm.setSuperClass(Proxy.class);
        ccm.addMethod("public Object newInstance(" + InvocationHandler.class.getName() + " h){ return new " + pcn + "($1); }");
        // 這里直接調用toClass方法生成Class,使用了 Javaassist 框架
        Class<?> pc = ccm.toClass();
        proxy = (Proxy) pc.newInstance();
    } catch (RuntimeException e) {
        throw e;
    } catch (Exception e) {
        throw new RuntimeException(e.getMessage(), e);
    } finally {
        // release ClassGenerator
        if (ccp != null)
            ccp.release();
        if (ccm != null)
            ccm.release();
        synchronized (cache) {
            if (proxy == null)
                cache.remove(key);
            else
                cache.put(key, new WeakReference<Proxy>(proxy));
            cache.notifyAll();
        }
    }
    return proxy;
}

 

如通過接口中的String sayHello(String arg0) 方法生成代理類的sayHello方法
public java.lang.String sayHello(java.lang.String arg0){
    Object[] args = new Object[1]; 
    args[0] = ($w)$1; 
    Object ret = handler.invoke(this, methods[0], args); 
    return (java.lang.String)ret;
}

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM