dubbo MethodConfig 源码

  • 2022-10-20
  • 浏览 (460)

dubbo MethodConfig 代码

文件路径:/dubbo-common/src/main/java/org/apache/dubbo/config/MethodConfig.java

/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.dubbo.config;

import org.apache.dubbo.common.config.Environment;
import org.apache.dubbo.common.config.InmemoryConfiguration;
import org.apache.dubbo.common.utils.ClassUtils;
import org.apache.dubbo.common.utils.MethodUtils;
import org.apache.dubbo.common.utils.ReflectUtils;
import org.apache.dubbo.common.utils.StringUtils;
import org.apache.dubbo.config.annotation.Method;
import org.apache.dubbo.config.support.Parameter;
import org.apache.dubbo.rpc.model.AsyncMethodInfo;
import org.apache.dubbo.rpc.model.ModuleModel;
import org.apache.dubbo.rpc.model.ScopeModelUtil;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import static org.apache.dubbo.config.Constants.ON_INVOKE_INSTANCE_PARAMETER_KEY;
import static org.apache.dubbo.config.Constants.ON_INVOKE_METHOD_PARAMETER_KEY;
import static org.apache.dubbo.config.Constants.ON_RETURN_INSTANCE_PARAMETER_KEY;
import static org.apache.dubbo.config.Constants.ON_RETURN_METHOD_PARAMETER_KEY;
import static org.apache.dubbo.config.Constants.ON_THROW_INSTANCE_PARAMETER_KEY;
import static org.apache.dubbo.config.Constants.ON_THROW_METHOD_PARAMETER_KEY;

/**
 * The method configuration
 *
 * @export
 */
public class MethodConfig extends AbstractMethodConfig {

    private static final long serialVersionUID = 884908855422675941L;

    /**
     * The method name
     */
    private String name;

    /**
     * Stat
     */
    private Integer stat;

    /**
     * Whether to retry
     */
    private Boolean retry;

    /**
     * If it's reliable
     */
    private Boolean reliable;

    /**
     * Thread limits for method invocations
     */
    private Integer executes;

    /**
     * If it's deprecated
     */
    private Boolean deprecated;

    /**
     * Whether to enable sticky
     */
    private Boolean sticky;

    /**
     * Whether you need to return
     */
    private Boolean isReturn;

    /**
     * Callback instance when async-call is invoked
     */
    private Object oninvoke;

    /**
     * Callback method when async-call is invoked
     */
    private String oninvokeMethod;

    /**
     * Callback instance when async-call is returned
     */
    private Object onreturn;

    /**
     * Callback method when async-call is returned
     */
    private String onreturnMethod;

    /**
     * Callback instance when async-call has exception thrown
     */
    private Object onthrow;

    /**
     * Callback method when async-call has exception thrown
     */
    private String onthrowMethod;

    /**
     * The method arguments
     */
    private List<ArgumentConfig> arguments;

    /**
     * TODO remove service and serviceId
     * These properties come from MethodConfig's parent Config module, they will neither be collected directly from xml or API nor be delivered to url
     */
    private String service;
    private String serviceId;

    /**
     * The preferred prefix of parent
     */
    private String parentPrefix;


    public MethodConfig() {
    }

    public MethodConfig(ModuleModel moduleModel) {
        super(moduleModel);
    }

    /**
     * TODO remove this construct, the callback method processing logic needs to rely on Spring context
     */
    @Deprecated
    public MethodConfig(Method method) {
        appendAnnotation(Method.class, method);

        this.setReturn(method.isReturn());

        String split = ".";

        if (!"".equals(method.oninvoke()) && method.oninvoke().lastIndexOf(split) > 0) {
            int index = method.oninvoke().lastIndexOf(split);
            String ref = method.oninvoke().substring(0, index);
            String methodName = method.oninvoke().substring(index + 1);
            this.setOninvoke(ref);
            this.setOninvokeMethod(methodName);
        }
        if (!"".equals(method.onreturn()) && method.onreturn().lastIndexOf(split) > 0) {
            int index = method.onreturn().lastIndexOf(split);
            String ref = method.onreturn().substring(0, index);
            String methodName = method.onreturn().substring(index + 1);
            this.setOnreturn(ref);
            this.setOnreturnMethod(methodName);
        }
        if (!"".equals(method.onthrow()) && method.onthrow().lastIndexOf(split) > 0) {
            int index = method.onthrow().lastIndexOf(split);
            String ref = method.onthrow().substring(0, index);
            String methodName = method.onthrow().substring(index + 1);
            this.setOnthrow(ref);
            this.setOnthrowMethod(methodName);
        }

        if (method.arguments() != null && method.arguments().length != 0) {
            List<ArgumentConfig> argumentConfigs = new ArrayList<>(method.arguments().length);
            this.setArguments(argumentConfigs);
            for (int i = 0; i < method.arguments().length; i++) {
                ArgumentConfig argumentConfig = new ArgumentConfig(method.arguments()[i]);
                argumentConfigs.add(argumentConfig);
            }
        }
    }

    /**
     * TODO remove constructMethodConfig
     *
     * @param methods
     * @return
     */
    @Deprecated
    public static List<MethodConfig> constructMethodConfig(Method[] methods) {
        if (methods != null && methods.length != 0) {
            List<MethodConfig> methodConfigs = new ArrayList<>(methods.length);
            for (int i = 0; i < methods.length; i++) {
                MethodConfig methodConfig = new MethodConfig(methods[i]);
                methodConfigs.add(methodConfig);
            }
            return methodConfigs;
        }
        return Collections.emptyList();
    }

    /**
     * Get method prefixes
     *
     * @return
     */
    @Override
    @Parameter(excluded = true, attribute = false)
    public List<String> getPrefixes() {
        // parent prefix + method name
        if (parentPrefix != null) {
            List<String> prefixes = new ArrayList<>();
            prefixes.add(parentPrefix + "." + this.getName());
            return prefixes;
        } else {
            throw new IllegalStateException("The parent prefix of MethodConfig is null");
        }
    }

    @Override
    protected void processExtraRefresh(String preferredPrefix, InmemoryConfiguration subPropsConfiguration) {
        // refresh ArgumentConfigs
        if (this.getArguments() != null && this.getArguments().size() > 0) {
            for (ArgumentConfig argument : this.getArguments()) {
                refreshArgument(argument, subPropsConfiguration);
            }
        }
    }

    private void refreshArgument(ArgumentConfig argument, InmemoryConfiguration subPropsConfiguration) {
        if (argument.getIndex() != null && argument.getIndex() >= 0) {
            String prefix = argument.getIndex() + ".";
            Environment environment = getScopeModel().getModelEnvironment();
            List<java.lang.reflect.Method> methods = MethodUtils.getMethods(argument.getClass(),
                method -> method.getDeclaringClass() != Object.class);
            for (java.lang.reflect.Method method : methods) {
                if (MethodUtils.isSetter(method)) {
                    String propertyName = extractPropertyName(method.getName());
                    // ignore attributes: 'index' / 'type'
                    if (StringUtils.isEquals(propertyName, "index") ||
                        StringUtils.isEquals(propertyName, "type")) {
                        continue;
                    }
                    // convert camelCase/snake_case to kebab-case
                    String kebabPropertyName = prefix + StringUtils.convertToSplitName(propertyName, "-");

                    try {
                        String value = StringUtils.trim(subPropsConfiguration.getString(kebabPropertyName));
                        if (StringUtils.hasText(value) && ClassUtils.isTypeMatch(method.getParameterTypes()[0], value)) {
                            value = environment.resolvePlaceholders(value);
                            method.invoke(argument, ClassUtils.convertPrimitive(ScopeModelUtil.getFrameworkModel(getScopeModel()), method.getParameterTypes()[0], value));
                        }
                    } catch (Exception e) {
                        logger.info("Failed to override the property " + method.getName() + " in " +
                            this.getClass().getSimpleName() +
                            ", please make sure every property has getter/setter method provided.");
                    }
                }
            }
        }
    }


    public AsyncMethodInfo convertMethodConfig2AsyncInfo() {
        if ((getOninvoke() == null && getOnreturn() == null && getOnthrow() == null)) {
            return null;
        }

        //check config conflict
        if (Boolean.FALSE.equals(isReturn()) && (getOnreturn() != null || getOnthrow() != null)) {
            throw new IllegalStateException("method config error : return attribute must be set true when on-return or on-throw has been set.");
        }

        AsyncMethodInfo asyncMethodInfo = new AsyncMethodInfo();

        asyncMethodInfo.setOninvokeInstance(getOninvoke());
        asyncMethodInfo.setOnreturnInstance(getOnreturn());
        asyncMethodInfo.setOnthrowInstance(getOnthrow());

        try {
            if (StringUtils.isNotEmpty(oninvokeMethod)) {
                asyncMethodInfo.setOninvokeMethod(getMethodByName(getOninvoke().getClass(), oninvokeMethod));
            }

            if (StringUtils.isNotEmpty(onreturnMethod)) {
                asyncMethodInfo.setOnreturnMethod(getMethodByName(getOnreturn().getClass(), onreturnMethod));
            }

            if (StringUtils.isNotEmpty(onthrowMethod)) {
                asyncMethodInfo.setOnthrowMethod(getMethodByName(getOnthrow().getClass(), onthrowMethod));
            }
        } catch (Exception e) {
            throw new IllegalStateException(e.getMessage(), e);
        }

        return asyncMethodInfo;
    }

    private java.lang.reflect.Method getMethodByName(Class<?> clazz, String methodName) {
        try {
            return ReflectUtils.findMethodByMethodName(clazz, methodName);
        } catch (Exception e) {
            throw new IllegalStateException(e);
        }
    }

    /**
     * Set default field values of MethodConfig.
     *
     * @see org.apache.dubbo.config.annotation.Method
     */
    @Override
    protected void checkDefault() {
        super.checkDefault();

        // set default field values
        // org.apache.dubbo.config.annotation.Method.isReturn() default true;
        if (isReturn() == null) {
            setReturn(true);
        }

        // org.apache.dubbo.config.annotation.Method.sent() default true;
        if (getSent() == null) {
            setSent(true);
        }
    }

    @Parameter(excluded = true)
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
        // FIXME, add id strategy in ConfigManager
//        if (StringUtils.isEmpty(id)) {
//            id = name;
//        }
    }

    public Integer getStat() {
        return stat;
    }

    @Deprecated
    public void setStat(Integer stat) {
        this.stat = stat;
    }

    @Deprecated
    public Boolean isRetry() {
        return retry;
    }

    @Deprecated
    public void setRetry(Boolean retry) {
        this.retry = retry;
    }

    @Deprecated
    public Boolean isReliable() {
        return reliable;
    }

    @Deprecated
    public void setReliable(Boolean reliable) {
        this.reliable = reliable;
    }

    public Integer getExecutes() {
        return executes;
    }

    public void setExecutes(Integer executes) {
        this.executes = executes;
    }

    public Boolean getDeprecated() {
        return deprecated;
    }

    public void setDeprecated(Boolean deprecated) {
        this.deprecated = deprecated;
    }

    public List<ArgumentConfig> getArguments() {
        return arguments;
    }

    @SuppressWarnings("unchecked")
    public void setArguments(List<? extends ArgumentConfig> arguments) {
        this.arguments = (List<ArgumentConfig>) arguments;
    }

    public Boolean getSticky() {
        return sticky;
    }

    public void setSticky(Boolean sticky) {
        this.sticky = sticky;
    }

    @Parameter(key = ON_RETURN_INSTANCE_PARAMETER_KEY, excluded = true, attribute = true)
    public Object getOnreturn() {
        return onreturn;
    }

    public void setOnreturn(Object onreturn) {
        this.onreturn = onreturn;
    }

    @Parameter(key = ON_RETURN_METHOD_PARAMETER_KEY, excluded = true, attribute = true)
    public String getOnreturnMethod() {
        return onreturnMethod;
    }

    public void setOnreturnMethod(String onreturnMethod) {
        this.onreturnMethod = onreturnMethod;
    }

    @Parameter(key = ON_THROW_INSTANCE_PARAMETER_KEY, excluded = true, attribute = true)
    public Object getOnthrow() {
        return onthrow;
    }

    public void setOnthrow(Object onthrow) {
        this.onthrow = onthrow;
    }

    @Parameter(key = ON_THROW_METHOD_PARAMETER_KEY, excluded = true, attribute = true)
    public String getOnthrowMethod() {
        return onthrowMethod;
    }

    public void setOnthrowMethod(String onthrowMethod) {
        this.onthrowMethod = onthrowMethod;
    }

    @Parameter(key = ON_INVOKE_INSTANCE_PARAMETER_KEY, excluded = true, attribute = true)
    public Object getOninvoke() {
        return oninvoke;
    }

    public void setOninvoke(Object oninvoke) {
        this.oninvoke = oninvoke;
    }

    @Parameter(key = ON_INVOKE_METHOD_PARAMETER_KEY, excluded = true, attribute = true)
    public String getOninvokeMethod() {
        return oninvokeMethod;
    }

    public void setOninvokeMethod(String oninvokeMethod) {
        this.oninvokeMethod = oninvokeMethod;
    }

    public Boolean isReturn() {
        return isReturn;
    }

    public void setReturn(Boolean isReturn) {
        this.isReturn = isReturn;
    }

    @Parameter(excluded = true, attribute = false)
    public String getService() {
        return service;
    }

    public void setService(String service) {
        this.service = service;
    }

    @Parameter(excluded = true, attribute = false)
    public String getServiceId() {
        return serviceId;
    }

    public void setServiceId(String serviceId) {
        this.serviceId = serviceId;
    }

    public void setParentPrefix(String parentPrefix) {
        this.parentPrefix = parentPrefix;
    }

    @Parameter(excluded = true, attribute = false)
    public String getParentPrefix() {
        return parentPrefix;
    }

    public void addArgument(ArgumentConfig argumentConfig) {
        if (arguments == null) {
            arguments = new ArrayList<>();
        }
        arguments.add(argumentConfig);
    }
}

相关信息

dubbo 源码目录

相关文章

dubbo AbstractConfig 源码

dubbo AbstractInterfaceConfig 源码

dubbo AbstractMethodConfig 源码

dubbo AbstractReferenceConfig 源码

dubbo AbstractServiceConfig 源码

dubbo ApplicationConfig 源码

dubbo ArgumentConfig 源码

dubbo ConfigCenterConfig 源码

dubbo ConfigKeys 源码

dubbo Constants 源码

0  赞