com.alipay.sofa.rpc.boot.runtime.converter.RpcBindingConverter Maven / Gradle / Ivy
/*
* 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 com.alipay.sofa.rpc.boot.runtime.converter;
import com.alipay.sofa.rpc.boot.common.SofaBootRpcParserUtil;
import com.alipay.sofa.rpc.boot.common.SofaBootRpcRuntimeException;
import com.alipay.sofa.rpc.boot.common.SofaBootRpcSpringUtil;
import com.alipay.sofa.rpc.boot.container.RpcFilterContainer;
import com.alipay.sofa.rpc.boot.runtime.binding.RpcBinding;
import com.alipay.sofa.rpc.boot.runtime.binding.RpcBindingMethodInfo;
import com.alipay.sofa.rpc.boot.runtime.binding.RpcBindingXmlConstants;
import com.alipay.sofa.rpc.boot.runtime.param.RpcBindingParam;
import com.alipay.sofa.rpc.config.UserThreadPoolManager;
import com.alipay.sofa.rpc.filter.ExcludeFilter;
import com.alipay.sofa.rpc.filter.Filter;
import com.alipay.sofa.rpc.server.UserThreadPool;
import com.alipay.sofa.runtime.api.annotation.SofaMethod;
import com.alipay.sofa.runtime.api.annotation.SofaParameter;
import com.alipay.sofa.runtime.api.annotation.SofaReference;
import com.alipay.sofa.runtime.api.annotation.SofaReferenceBinding;
import com.alipay.sofa.runtime.api.annotation.SofaService;
import com.alipay.sofa.runtime.api.annotation.SofaServiceBinding;
import com.alipay.sofa.runtime.spi.service.BindingConverter;
import com.alipay.sofa.runtime.spi.service.BindingConverterContext;
import org.springframework.context.ApplicationContext;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.util.xml.DomUtils;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
/**
* 解析 XML配置或者 {@link RpcBindingParam} 为 {@link RpcBinding}
*
* @author CaoJie
* @author LiWei
*/
public abstract class RpcBindingConverter implements BindingConverter {
private static final String FILTER_SEPERATOR_SYMBOL = ",";
private static final char EXCLUDE_FILTER_BEGIN_SYMBOL = '!';
/**
* convert {@link RpcBindingParam} to concrete {@link RpcBinding}
*
* @param bindingParam binding parameter
* @param bindingConverterContext binding converter context
* @return RpcBinding Object
*/
@Override
public RpcBinding convert(RpcBindingParam bindingParam,
BindingConverterContext bindingConverterContext) {
RpcBinding binding = createRpcBinding(bindingParam,
bindingConverterContext.getApplicationContext(), bindingConverterContext.isInBinding());
setCallback(bindingParam, bindingConverterContext);
binding.setAppName(bindingConverterContext.getAppName());
binding.setBeanId(bindingConverterContext.getBeanId());
return binding;
}
/**
* convert xml Element to concrete {@link RpcBinding}
*
* @param element xml Element
* @param bindingConverterContext binding converter context
* @return RpcBinding Object
*/
@Override
public RpcBinding convert(Element element, BindingConverterContext bindingConverterContext) {
RpcBindingParam param = createRpcBindingParam();
//global-attrs,filter,method,route
Element globalAttrsElement = DomUtils.getChildElementByTagName(element,
RpcBindingXmlConstants.TAG_GLOBAL_ATTRS);
Element routeElement = DomUtils.getChildElementByTagName(element,
RpcBindingXmlConstants.TAG_ROUTE);
List methodElements = DomUtils.getChildElementsByTagName(element,
RpcBindingXmlConstants.TAG_METHOD);
List parameterElements = DomUtils.getChildElementsByTagName(element,
RpcBindingXmlConstants.TAG_PARAMETER);
parseGlobalAttrs(globalAttrsElement, param, bindingConverterContext);
parseFilter(globalAttrsElement, param, bindingConverterContext);
parseMethod(methodElements, param);
parseRoute(routeElement, param);
parseParameter(parameterElements, param);
return convert(param, bindingConverterContext);
}
/**
* 创建 RpcBinding
*
* @param bindingParam the RpcBindingParam
* @param applicationContext spring 上下文
* @param inBinding 是否是服务引用
* @return the RpcBinding
*/
protected abstract RpcBinding createRpcBinding(RpcBindingParam bindingParam,
ApplicationContext applicationContext,
boolean inBinding);
/**
* 创建 RpcBindingParam
*
* @return the RpcBindingParam
*/
protected abstract RpcBindingParam createRpcBindingParam();
protected void parseMethod(List elements, RpcBindingParam param) {
if (CollectionUtils.isEmpty(elements)) {
return;
}
List boltBindingMethodInfos = new ArrayList();
for (Element element : elements) {
if (element.getNodeType() == Node.ELEMENT_NODE
&& element.getLocalName().equals(RpcBindingXmlConstants.TAG_METHOD)) {
String name = element.getAttribute(RpcBindingXmlConstants.TAG_NAME);
Integer timeout = SofaBootRpcParserUtil.parseInteger(element
.getAttribute(RpcBindingXmlConstants.TAG_TIMEOUT));
Integer retries = SofaBootRpcParserUtil.parseInteger(element
.getAttribute(RpcBindingXmlConstants.TAG_RETRIES));
String type = element.getAttribute(RpcBindingXmlConstants.TAG_TYPE);
RpcBindingMethodInfo boltBindingMethodInfo = new RpcBindingMethodInfo();
if (StringUtils.hasText(name)) {
boltBindingMethodInfo.setName(name);
}
if (timeout != null) {
boltBindingMethodInfo.setTimeout(timeout);
}
if (retries != null) {
boltBindingMethodInfo.setRetries(retries);
}
if (StringUtils.hasText(type)) {
boltBindingMethodInfo.setType(type);
}
if (type.equalsIgnoreCase(RpcBindingXmlConstants.TYPE_CALLBACK)) {
String callbackRef = element
.getAttribute(RpcBindingXmlConstants.TAG_CALLBACK_REF);
String callbackClass = element
.getAttribute(RpcBindingXmlConstants.TAG_CALLBACK_CLASS);
boltBindingMethodInfo.setCallbackRef(callbackRef);
boltBindingMethodInfo.setCallbackClass(callbackClass);
}
boltBindingMethodInfos.add(boltBindingMethodInfo);
}
}
param.setMethodInfos(boltBindingMethodInfos);
}
protected void parseParameter(List parameterElements, RpcBindingParam param) {
if (CollectionUtils.isEmpty(parameterElements)) {
return;
}
Map parameters = new LinkedHashMap(parameterElements.size());
for (Element element : parameterElements) {
if (element.getNodeType() == Node.ELEMENT_NODE
&& element.getLocalName().equals(RpcBindingXmlConstants.TAG_PARAMETER)) {
String key = element.getAttribute(RpcBindingXmlConstants.TAG_PARAMETER_KEY);
String value = element.getAttribute(RpcBindingXmlConstants.TAG_PARAMETER_VALUE);
parameters.put(key, value);
}
}
param.setParameters(parameters);
}
protected void parseGlobalAttrs(Element element, RpcBindingParam param,
BindingConverterContext bindingConverterContext) {
if (element == null) {
return;
}
Integer timeout = SofaBootRpcParserUtil.parseInteger(element
.getAttribute(RpcBindingXmlConstants.TAG_TIMEOUT));
Integer addressWaitTime = SofaBootRpcParserUtil.parseInteger(element
.getAttribute(RpcBindingXmlConstants.TAG_ADDRESS_WAIT_TIME));
Integer connectTimeout = SofaBootRpcParserUtil.parseInteger(element
.getAttribute(RpcBindingXmlConstants.TAG_CONNECT_TIMEOUT));
Integer connectionNum = SofaBootRpcParserUtil.parseInteger(element
.getAttribute(RpcBindingXmlConstants.TAG_CONNECT_NUM));
Integer retries = SofaBootRpcParserUtil.parseInteger(element
.getAttribute(RpcBindingXmlConstants.TAG_RETRIES));
String type = element.getAttribute(RpcBindingXmlConstants.TAG_TYPE);
String callbackClass = element.getAttribute(RpcBindingXmlConstants.TAG_CALLBACK_CLASS);
String callbackRef = element.getAttribute(RpcBindingXmlConstants.TAG_CALLBACK_REF);
Integer weight = SofaBootRpcParserUtil.parseInteger(element
.getAttribute(RpcBindingXmlConstants.TAG_WEIGHT));
Integer warmUpTime = SofaBootRpcParserUtil.parseInteger(element
.getAttribute(RpcBindingXmlConstants.TAG_WARMUP_TIME));
Integer warmUpWeight = SofaBootRpcParserUtil.parseInteger(element
.getAttribute(RpcBindingXmlConstants.TAG_WARMUP_WEIGHT));
Object treadPoolRef = SofaBootRpcSpringUtil.getSpringBean(
element.getAttribute(RpcBindingXmlConstants.TAG_THREAD_POOL_REF),
bindingConverterContext.getApplicationContext(),
bindingConverterContext.getAppClassLoader(), bindingConverterContext.getAppName());
String genericInterface = element
.getAttribute(RpcBindingXmlConstants.TAG_GENERIC_INTERFACE);
String loadBalancer = element.getAttribute(RpcBindingXmlConstants.TAG_LOAD_BALANCER);
Boolean lazy = SofaBootRpcParserUtil.parseBoolean(element
.getAttribute(RpcBindingXmlConstants.TAG_LAZY));
Boolean check = SofaBootRpcParserUtil.parseBoolean(element
.getAttribute(RpcBindingXmlConstants.TAG_CHECK));
String registryAlias = element.getAttribute(RpcBindingXmlConstants.TAG_REGISTRY);
String mockMode = element.getAttribute(RpcBindingXmlConstants.TAG_MOCK_MODE);
String mockBean = element.getAttribute(RpcBindingXmlConstants.TAG_MOCK_BEAN);
String serialization = element.getAttribute(RpcBindingXmlConstants.TAG_SERIALIZE_TYPE);
if (timeout != null) {
param.setTimeout(timeout);
}
if (addressWaitTime != null) {
param.setAddressWaitTime(addressWaitTime);
}
if (connectTimeout != null) {
param.setConnectTimeout(connectTimeout);
}
if (retries != null) {
param.setRetries(retries);
}
if (StringUtils.hasText(type)) {
param.setType(type);
}
if (StringUtils.hasText(callbackClass)) {
param.setCallbackClass(callbackClass);
}
if (StringUtils.hasText(callbackRef)) {
param.setCallbackRef(callbackRef);
}
if (weight != null) {
param.setWeight(weight);
}
if (warmUpTime != null) {
param.setWarmUpTime(warmUpTime);
}
if (warmUpWeight != null) {
param.setWarmUpWeight(warmUpWeight);
}
if (treadPoolRef != null) {
param.setUserThreadPool((UserThreadPool) treadPoolRef);
}
if (StringUtils.hasText(genericInterface)) {
param.setGenericInterface(genericInterface);
}
if (StringUtils.hasText(loadBalancer)) {
param.setLoadBalancer(loadBalancer);
}
if (connectionNum != null) {
param.setConnectionNum(connectionNum);
}
if (lazy != null) {
param.setLazy(lazy);
}
if (check != null) {
param.setCheck(check);
}
if (StringUtils.hasText(serialization)) {
param.setSerialization(serialization);
}
if (StringUtils.hasText(registryAlias)) {
String[] registrys = registryAlias.split(",");
param.setRegistrys(Arrays.asList(registrys));
}
if (StringUtils.hasText(mockMode)) {
param.setMockMode(mockMode);
}
if (StringUtils.hasText(mockBean)) {
param.setMockBean(mockBean);
}
}
protected void parseFilter(Element element, RpcBindingParam param,
BindingConverterContext bindingConverterContext) {
List filters = new ArrayList(RpcFilterContainer.getInstance().getFilters(
bindingConverterContext.getApplicationContext()));
if (element != null) {
List filterNames = new ArrayList();
String filterStrs = element.getAttribute(RpcBindingXmlConstants.TAG_FILTER);
if (StringUtils.hasText(filterStrs)) {
String[] subFilter = filterStrs.split(FILTER_SEPERATOR_SYMBOL);
for (String subfilterName : subFilter) {
if (StringUtils.hasText(subfilterName)) {
if (subfilterName.charAt(0) == EXCLUDE_FILTER_BEGIN_SYMBOL) {
String realFilterName = subfilterName.substring(1);
if (StringUtils.hasText(realFilterName)) {
filters.add(new ExcludeFilter(realFilterName));
}
} else {
filterNames.add(subfilterName);
}
}
}
}
if (!CollectionUtils.isEmpty(filterNames)) {
for (String filterName : filterNames) {
Object filter = bindingConverterContext.getApplicationContext().getBean(
filterName);
if (filter instanceof Filter) {
filters.add((Filter) filter);
} else {
throw new SofaBootRpcRuntimeException("filter name[" + filterName
+ "] is not ref a Filter.");
}
}
}
}
param.setFilters(filters);
}
protected void parseRoute(Element routeElement, RpcBindingParam param) {
if (routeElement == null) {
return;
}
String targetUrl = routeElement.getAttribute(RpcBindingXmlConstants.TAG_TARGET_URL);
if (StringUtils.hasText(targetUrl)) {
param.setTargetUrl(targetUrl);
}
}
protected void setCallback(RpcBindingParam bindingParam,
BindingConverterContext bindingConverterContext) {
//global
if (bindingParam.getCallbackHandler() == null) {
Object globalCallbackHandler = SofaBootRpcSpringUtil.getSpringBean(
bindingParam.getCallbackRef(), bindingParam.getCallbackClass(),
bindingConverterContext.getApplicationContext(),
bindingConverterContext.getAppClassLoader(), bindingConverterContext.getAppName());
if (globalCallbackHandler != null) {
bindingParam.setCallbackHandler(globalCallbackHandler);
}
}
//method
if (!CollectionUtils.isEmpty(bindingParam.getMethodInfos())) {
for (RpcBindingMethodInfo methodInfo : bindingParam.getMethodInfos()) {
Object methodCallbackHandler = methodInfo.getCallbackHandler();
if (methodCallbackHandler == null) {
methodCallbackHandler = SofaBootRpcSpringUtil.getSpringBean(
methodInfo.getCallbackRef(), methodInfo.getCallbackClass(),
bindingConverterContext.getApplicationContext(),
bindingConverterContext.getAppClassLoader(),
bindingConverterContext.getAppName());
methodInfo.setCallbackHandler(methodCallbackHandler);
}
}
}
}
/**
* transfer sofa service annotation
*
* @param sofaServiceAnnotation
* @param sofaServiceBindingAnnotation
* @param bindingConverterContext
* @return
*/
@Override
public abstract RpcBinding convert(SofaService sofaServiceAnnotation,
SofaServiceBinding sofaServiceBindingAnnotation,
BindingConverterContext bindingConverterContext);
/**
* convert props to RpcBindingParam
*
* @param bindingParam
* @param sofaServiceAnnotation
* @param sofaServiceBindingAnnotation
* @param bindingConverterContext
*/
protected void convertServiceAnnotation(RpcBindingParam bindingParam,
SofaService sofaServiceAnnotation,
SofaServiceBinding sofaServiceBindingAnnotation,
BindingConverterContext bindingConverterContext) {
if (sofaServiceBindingAnnotation.timeout() != 0) {
bindingParam.setTimeout(sofaServiceBindingAnnotation.timeout());
}
//TODO need a magic number
if (sofaServiceBindingAnnotation.weight() != 0) {
bindingParam.setWeight(sofaServiceBindingAnnotation.weight());
}
if (sofaServiceBindingAnnotation.warmUpTime() != 0) {
bindingParam.setWarmUpTime(sofaServiceBindingAnnotation.warmUpTime());
}
if (sofaServiceBindingAnnotation.warmUpWeight() != 0) {
bindingParam.setWarmUpWeight(sofaServiceBindingAnnotation.warmUpWeight());
}
if (StringUtils.hasText(sofaServiceBindingAnnotation.serializeType())) {
bindingParam.setSerialization(sofaServiceBindingAnnotation.serializeType());
}
ApplicationContext applicationContext = bindingConverterContext.getApplicationContext();
List filters = new ArrayList(RpcFilterContainer.getInstance().getFilters(
applicationContext));
String[] filterNames = sofaServiceBindingAnnotation.filters();
if (filterNames.length > 0) {
for (String filterName : filterNames) {
Object filter = applicationContext.getBean(filterName);
if (filter instanceof Filter) {
filters.add((Filter) filter);
} else {
throw new SofaBootRpcRuntimeException("filter name[" + filterName
+ "] is not ref a Filter.");
}
}
}
if (!CollectionUtils.isEmpty(filters)) {
bindingParam.setFilters(filters);
}
String threadPool = sofaServiceBindingAnnotation.userThreadPool();
if (StringUtils.hasText(threadPool)) {
UserThreadPool threadPoolObj = (UserThreadPool) applicationContext.getBean(threadPool);
String interfaceName = sofaServiceAnnotation.interfaceType().getCanonicalName();
String uniqId = sofaServiceAnnotation.uniqueId();
String uniqueName = interfaceName + ":1.0"
+ (StringUtils.isEmpty(uniqId) ? "" : ":" + uniqId);
UserThreadPoolManager.registerUserThread(uniqueName, threadPoolObj);
}
String registryAlias = sofaServiceBindingAnnotation.registry();
if (StringUtils.hasText(registryAlias)) {
String[] registrys = registryAlias.split(",");
bindingParam.setRegistrys(Arrays.asList(registrys));
}
SofaParameter[] parameters = sofaServiceBindingAnnotation.parameters();
if (parameters.length > 0) {
bindingParam.setParameters(parseSofaParameters(parameters));
}
SofaMethod[] sofaMethods = sofaServiceBindingAnnotation.methodInfos();
if (sofaMethods.length > 0) {
bindingParam.setMethodInfos(parseSofaMethods(sofaMethods));
}
}
/**
* transfer sofareference annotation
*
* @param sofaReferenceAnnotation
* @param sofaReferenceBindingAnnotation
* @param bindingConverterContext
* @return
*/
@Override
public abstract RpcBinding convert(SofaReference sofaReferenceAnnotation,
SofaReferenceBinding sofaReferenceBindingAnnotation,
BindingConverterContext bindingConverterContext);
/**
* convert props to RpcBindingParam
*
* @param bindingParam
* @param sofaReferenceBindingAnnotation
* @param bindingConverterContext
*/
protected void convertReferenceAnnotation(RpcBindingParam bindingParam,
SofaReferenceBinding sofaReferenceBindingAnnotation,
BindingConverterContext bindingConverterContext) {
if (sofaReferenceBindingAnnotation.addressWaitTime() != 0) {
bindingParam.setAddressWaitTime(sofaReferenceBindingAnnotation.addressWaitTime());
}
if (StringUtils.hasText(sofaReferenceBindingAnnotation.directUrl())) {
bindingParam.setTargetUrl(sofaReferenceBindingAnnotation.directUrl());
}
if (sofaReferenceBindingAnnotation.timeout() != 0) {
bindingParam.setTimeout(sofaReferenceBindingAnnotation.timeout());
}
if (StringUtils.hasText(sofaReferenceBindingAnnotation.serializeType())) {
bindingParam.setSerialization(sofaReferenceBindingAnnotation.serializeType());
}
if (StringUtils.hasText(sofaReferenceBindingAnnotation.loadBalancer())) {
bindingParam.setLoadBalancer(sofaReferenceBindingAnnotation.loadBalancer());
}
if (StringUtils.hasText(sofaReferenceBindingAnnotation.mockMode())) {
bindingParam.setMockMode(sofaReferenceBindingAnnotation.mockMode());
}
if (StringUtils.hasText(sofaReferenceBindingAnnotation.mockBean())) {
bindingParam.setMockBean(sofaReferenceBindingAnnotation.mockBean());
}
bindingParam.setType(sofaReferenceBindingAnnotation.invokeType());
ApplicationContext applicationContext = bindingConverterContext.getApplicationContext();
List filters = new ArrayList(RpcFilterContainer.getInstance().getFilters(
applicationContext));
String[] filterNames = sofaReferenceBindingAnnotation.filters();
if (filterNames.length > 0) {
for (String filterName : filterNames) {
Object filter = applicationContext.getBean(filterName);
if (filter instanceof Filter) {
filters.add((Filter) filter);
} else {
throw new SofaBootRpcRuntimeException("filter name[" + filterName
+ "] is not ref a Filter.");
}
}
}
if (!CollectionUtils.isEmpty(filters)) {
bindingParam.setFilters(filters);
}
bindingParam.setRetries(sofaReferenceBindingAnnotation.retries());
String callbackRef = sofaReferenceBindingAnnotation.callbackHandler();
if (StringUtils.hasText(callbackRef)) {
bindingParam.setCallbackHandler(applicationContext.getBean(callbackRef));
}
bindingParam.setConnectionNum(sofaReferenceBindingAnnotation.connectionNum());
bindingParam.setLazy(sofaReferenceBindingAnnotation.lazy());
String registryAlias = sofaReferenceBindingAnnotation.registry();
if (StringUtils.hasText(registryAlias)) {
String[] registrys = registryAlias.split(",");
bindingParam.setRegistrys(Arrays.asList(registrys));
}
SofaParameter[] parameters = sofaReferenceBindingAnnotation.parameters();
if (parameters.length > 0) {
bindingParam.setParameters(parseSofaParameters(parameters));
}
SofaMethod[] sofaMethods = sofaReferenceBindingAnnotation.methodInfos();
if (sofaMethods.length > 0) {
bindingParam.setMethodInfos(parseSofaMethods(sofaMethods));
}
}
public List parseSofaMethods(SofaMethod[] sofaMethods) {
List rpcBindingMethodInfos = new ArrayList();
for (SofaMethod sofaMethod : sofaMethods) {
RpcBindingMethodInfo rpcBindingMethodInfo = new RpcBindingMethodInfo();
rpcBindingMethodInfo.setName(sofaMethod.name());
rpcBindingMethodInfo.setType(sofaMethod.invokeType());
rpcBindingMethodInfo.setTimeout(sofaMethod.timeout());
rpcBindingMethodInfo.setRetries(sofaMethod.retries());
rpcBindingMethodInfo.setCallbackClass(sofaMethod.callbackClass());
rpcBindingMethodInfo.setCallbackRef(sofaMethod.callbackRef());
rpcBindingMethodInfos.add(rpcBindingMethodInfo);
}
return rpcBindingMethodInfos;
}
protected Map parseSofaParameters(SofaParameter[] parameterAnnos) {
Map parameters = new LinkedHashMap();
for (SofaParameter parameter : parameterAnnos) {
parameters.put(parameter.key(), parameter.value());
}
return parameters;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy