mirror of
https://gitee.com/mirrors/Spring-Cloud-Alibaba.git
synced 2021-06-26 13:25:11 +08:00
polish #761 update pkg name & maven coordinate for Greenwich
This commit is contained in:
@@ -0,0 +1,87 @@
|
||||
/*
|
||||
* 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.alibaba.cloud.dubbo.openfeign;
|
||||
|
||||
import org.apache.dubbo.rpc.service.GenericService;
|
||||
|
||||
import com.alibaba.cloud.dubbo.metadata.RestMethodMetadata;
|
||||
import com.alibaba.cloud.dubbo.service.DubboGenericServiceExecutionContext;
|
||||
import com.alibaba.cloud.dubbo.service.DubboGenericServiceExecutionContextFactory;
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
import java.lang.reflect.InvocationHandler;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.apache.dubbo.common.utils.PojoUtils.realize;
|
||||
|
||||
/**
|
||||
* Dubbo {@link GenericService} for {@link InvocationHandler}
|
||||
*
|
||||
* @author <a href="mailto:mercyblitz@gmail.com">Mercy</a>
|
||||
*/
|
||||
public class DubboInvocationHandler implements InvocationHandler {
|
||||
|
||||
private final Map<Method, FeignMethodMetadata> feignMethodMetadataMap;
|
||||
|
||||
private final InvocationHandler defaultInvocationHandler;
|
||||
|
||||
private final DubboGenericServiceExecutionContextFactory contextFactory;
|
||||
|
||||
private final ClassLoader classLoader;
|
||||
|
||||
public DubboInvocationHandler(Map<Method, FeignMethodMetadata> feignMethodMetadataMap,
|
||||
InvocationHandler defaultInvocationHandler,
|
||||
ClassLoader classLoader,
|
||||
DubboGenericServiceExecutionContextFactory contextFactory) {
|
||||
this.feignMethodMetadataMap = feignMethodMetadataMap;
|
||||
this.defaultInvocationHandler = defaultInvocationHandler;
|
||||
this.classLoader = classLoader;
|
||||
this.contextFactory = contextFactory;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object invoke(Object proxy, Method feignMethod, Object[] args) throws Throwable {
|
||||
|
||||
FeignMethodMetadata feignMethodMetadata = feignMethodMetadataMap.get(feignMethod);
|
||||
|
||||
if (feignMethodMetadata == null) {
|
||||
return defaultInvocationHandler.invoke(proxy, feignMethod, args);
|
||||
}
|
||||
|
||||
GenericService dubboGenericService = feignMethodMetadata.getDubboGenericService();
|
||||
RestMethodMetadata dubboRestMethodMetadata = feignMethodMetadata.getDubboRestMethodMetadata();
|
||||
RestMethodMetadata feignRestMethodMetadata = feignMethodMetadata.getFeignMethodMetadata();
|
||||
|
||||
DubboGenericServiceExecutionContext context = contextFactory.create(dubboRestMethodMetadata, feignRestMethodMetadata, args);
|
||||
|
||||
String methodName = context.getMethodName();
|
||||
String[] parameterTypes = context.getParameterTypes();
|
||||
Object[] parameters = context.getParameters();
|
||||
|
||||
Object result = dubboGenericService.$invoke(methodName, parameterTypes, parameters);
|
||||
|
||||
Class<?> returnType = getReturnType(dubboRestMethodMetadata);
|
||||
|
||||
return realize(result, returnType);
|
||||
}
|
||||
|
||||
private Class<?> getReturnType(RestMethodMetadata dubboRestMethodMetadata) {
|
||||
String returnType = dubboRestMethodMetadata.getReturnType();
|
||||
return ClassUtils.resolveClassName(returnType, classLoader);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* 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.alibaba.cloud.dubbo.openfeign;
|
||||
|
||||
import org.apache.dubbo.rpc.service.GenericService;
|
||||
import com.alibaba.cloud.dubbo.metadata.RestMethodMetadata;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
/**
|
||||
* Feign {@link Method} Metadata
|
||||
*
|
||||
* @author <a href="mailto:mercyblitz@gmail.com">Mercy</a>
|
||||
*/
|
||||
class FeignMethodMetadata {
|
||||
|
||||
private final GenericService dubboGenericService;
|
||||
|
||||
private final RestMethodMetadata dubboRestMethodMetadata;
|
||||
|
||||
private final RestMethodMetadata feignMethodMetadata;
|
||||
|
||||
|
||||
FeignMethodMetadata(GenericService dubboGenericService, RestMethodMetadata dubboRestMethodMetadata,
|
||||
RestMethodMetadata feignMethodMetadata) {
|
||||
this.dubboGenericService = dubboGenericService;
|
||||
this.dubboRestMethodMetadata = dubboRestMethodMetadata;
|
||||
this.feignMethodMetadata = feignMethodMetadata;
|
||||
}
|
||||
|
||||
GenericService getDubboGenericService() {
|
||||
return dubboGenericService;
|
||||
}
|
||||
|
||||
RestMethodMetadata getDubboRestMethodMetadata() {
|
||||
return dubboRestMethodMetadata;
|
||||
}
|
||||
|
||||
RestMethodMetadata getFeignMethodMetadata() {
|
||||
return feignMethodMetadata;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
/*
|
||||
* 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.alibaba.cloud.dubbo.openfeign;
|
||||
|
||||
import com.alibaba.cloud.dubbo.service.DubboGenericServiceExecutionContextFactory;
|
||||
import com.alibaba.cloud.dubbo.service.DubboGenericServiceFactory;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.BeanClassLoaderAware;
|
||||
import org.springframework.beans.factory.config.BeanPostProcessor;
|
||||
import com.alibaba.cloud.dubbo.metadata.repository.DubboServiceMetadataRepository;
|
||||
|
||||
import org.springframework.core.env.Environment;
|
||||
|
||||
import static java.lang.reflect.Proxy.newProxyInstance;
|
||||
import static com.alibaba.cloud.dubbo.autoconfigure.DubboOpenFeignAutoConfiguration.TARGETER_CLASS_NAME;
|
||||
import static org.springframework.util.ClassUtils.getUserClass;
|
||||
import static org.springframework.util.ClassUtils.isPresent;
|
||||
import static org.springframework.util.ClassUtils.resolveClassName;
|
||||
|
||||
/**
|
||||
* org.springframework.cloud.openfeign.Targeter {@link BeanPostProcessor}
|
||||
*
|
||||
* @author <a href="mailto:mercyblitz@gmail.com">Mercy</a>
|
||||
*/
|
||||
public class TargeterBeanPostProcessor implements BeanPostProcessor, BeanClassLoaderAware {
|
||||
|
||||
private final Environment environment;
|
||||
|
||||
private final DubboServiceMetadataRepository dubboServiceMetadataRepository;
|
||||
|
||||
private final DubboGenericServiceFactory dubboGenericServiceFactory;
|
||||
|
||||
private final DubboGenericServiceExecutionContextFactory contextFactory;
|
||||
|
||||
private ClassLoader classLoader;
|
||||
|
||||
public TargeterBeanPostProcessor(Environment environment,
|
||||
DubboServiceMetadataRepository dubboServiceMetadataRepository,
|
||||
DubboGenericServiceFactory dubboGenericServiceFactory,
|
||||
DubboGenericServiceExecutionContextFactory contextFactory) {
|
||||
this.environment = environment;
|
||||
this.dubboServiceMetadataRepository = dubboServiceMetadataRepository;
|
||||
this.dubboGenericServiceFactory = dubboGenericServiceFactory;
|
||||
this.contextFactory = contextFactory;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
|
||||
return bean;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object postProcessAfterInitialization(final Object bean, String beanName) throws BeansException {
|
||||
if (isPresent(TARGETER_CLASS_NAME, classLoader)) {
|
||||
Class<?> beanClass = getUserClass(bean.getClass());
|
||||
Class<?> targetClass = resolveClassName(TARGETER_CLASS_NAME, classLoader);
|
||||
if (targetClass.isAssignableFrom(beanClass)) {
|
||||
return newProxyInstance(classLoader, new Class[]{targetClass},
|
||||
new TargeterInvocationHandler(bean, environment, classLoader, dubboServiceMetadataRepository,
|
||||
dubboGenericServiceFactory, contextFactory));
|
||||
}
|
||||
}
|
||||
return bean;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBeanClassLoader(ClassLoader classLoader) {
|
||||
this.classLoader = classLoader;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,175 @@
|
||||
/*
|
||||
* 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.alibaba.cloud.dubbo.openfeign;
|
||||
|
||||
|
||||
import org.apache.dubbo.rpc.service.GenericService;
|
||||
|
||||
import feign.Contract;
|
||||
import feign.Target;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import com.alibaba.cloud.dubbo.annotation.DubboTransported;
|
||||
import com.alibaba.cloud.dubbo.metadata.DubboRestServiceMetadata;
|
||||
import com.alibaba.cloud.dubbo.metadata.DubboTransportedMethodMetadata;
|
||||
import com.alibaba.cloud.dubbo.metadata.MethodMetadata;
|
||||
import com.alibaba.cloud.dubbo.metadata.RequestMetadata;
|
||||
import com.alibaba.cloud.dubbo.metadata.RestMethodMetadata;
|
||||
import com.alibaba.cloud.dubbo.metadata.repository.DubboServiceMetadataRepository;
|
||||
import com.alibaba.cloud.dubbo.metadata.resolver.DubboTransportedMethodMetadataResolver;
|
||||
import com.alibaba.cloud.dubbo.service.DubboGenericServiceExecutionContextFactory;
|
||||
import com.alibaba.cloud.dubbo.service.DubboGenericServiceFactory;
|
||||
import org.springframework.cloud.openfeign.FeignContext;
|
||||
import org.springframework.core.env.Environment;
|
||||
|
||||
import java.lang.reflect.InvocationHandler;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Proxy;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import static java.lang.reflect.Proxy.newProxyInstance;
|
||||
|
||||
/**
|
||||
* org.springframework.cloud.openfeign.Targeter {@link InvocationHandler}
|
||||
*
|
||||
* @author <a href="mailto:mercyblitz@gmail.com">Mercy</a>
|
||||
*/
|
||||
class TargeterInvocationHandler implements InvocationHandler {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(getClass());
|
||||
|
||||
private final Object bean;
|
||||
|
||||
private final Environment environment;
|
||||
|
||||
private final ClassLoader classLoader;
|
||||
|
||||
private final DubboServiceMetadataRepository repository;
|
||||
|
||||
private final DubboGenericServiceFactory dubboGenericServiceFactory;
|
||||
|
||||
private final DubboGenericServiceExecutionContextFactory contextFactory;
|
||||
|
||||
TargeterInvocationHandler(Object bean, Environment environment,
|
||||
ClassLoader classLoader,
|
||||
DubboServiceMetadataRepository repository,
|
||||
DubboGenericServiceFactory dubboGenericServiceFactory,
|
||||
DubboGenericServiceExecutionContextFactory contextFactory) {
|
||||
this.bean = bean;
|
||||
this.environment = environment;
|
||||
this.classLoader = classLoader;
|
||||
this.repository = repository;
|
||||
this.dubboGenericServiceFactory = dubboGenericServiceFactory;
|
||||
this.contextFactory = contextFactory;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
|
||||
/**
|
||||
* args[0]: FeignClientFactoryBean factory
|
||||
* args[1]: Feign.Builder feign
|
||||
* args[2]: FeignContext context
|
||||
* args[3]: Target.HardCodedTarget<T> target
|
||||
*/
|
||||
FeignContext feignContext = cast(args[2]);
|
||||
Target.HardCodedTarget<?> target = cast(args[3]);
|
||||
|
||||
// Execute Targeter#target method first
|
||||
method.setAccessible(true);
|
||||
// Get the default proxy object
|
||||
Object defaultProxy = method.invoke(bean, args);
|
||||
// Create Dubbo Proxy if required
|
||||
return createDubboProxyIfRequired(feignContext, target, defaultProxy);
|
||||
}
|
||||
|
||||
private Object createDubboProxyIfRequired(FeignContext feignContext, Target target, Object defaultProxy) {
|
||||
|
||||
DubboInvocationHandler dubboInvocationHandler = createDubboInvocationHandler(feignContext, target, defaultProxy);
|
||||
|
||||
if (dubboInvocationHandler == null) {
|
||||
return defaultProxy;
|
||||
}
|
||||
|
||||
return newProxyInstance(target.type().getClassLoader(), new Class<?>[]{target.type()}, dubboInvocationHandler);
|
||||
}
|
||||
|
||||
private DubboInvocationHandler createDubboInvocationHandler(FeignContext feignContext, Target target,
|
||||
Object defaultFeignClientProxy) {
|
||||
|
||||
// Service name equals @FeignClient.name()
|
||||
String serviceName = target.name();
|
||||
Class<?> targetType = target.type();
|
||||
|
||||
// Get Contract Bean from FeignContext
|
||||
Contract contract = feignContext.getInstance(serviceName, Contract.class);
|
||||
|
||||
DubboTransportedMethodMetadataResolver resolver =
|
||||
new DubboTransportedMethodMetadataResolver(environment, contract);
|
||||
|
||||
Map<DubboTransportedMethodMetadata, RestMethodMetadata> feignRestMethodMetadataMap = resolver.resolve(targetType);
|
||||
|
||||
if (feignRestMethodMetadataMap.isEmpty()) { // @DubboTransported method was not found from the Client interface
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("@{} method was not found in the Feign target type[{}]",
|
||||
DubboTransported.class.getSimpleName(), targetType.getName());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
// Update Metadata
|
||||
repository.initialize(serviceName);
|
||||
|
||||
Map<Method, FeignMethodMetadata> feignMethodMetadataMap = getFeignMethodMetadataMap(serviceName, feignRestMethodMetadataMap);
|
||||
|
||||
InvocationHandler defaultFeignClientInvocationHandler = Proxy.getInvocationHandler(defaultFeignClientProxy);
|
||||
|
||||
DubboInvocationHandler dubboInvocationHandler = new DubboInvocationHandler(feignMethodMetadataMap,
|
||||
defaultFeignClientInvocationHandler, classLoader, contextFactory);
|
||||
|
||||
return dubboInvocationHandler;
|
||||
}
|
||||
|
||||
private Map<Method, FeignMethodMetadata> getFeignMethodMetadataMap(String serviceName,
|
||||
Map<DubboTransportedMethodMetadata, RestMethodMetadata>
|
||||
feignRestMethodMetadataMap) {
|
||||
Map<Method, FeignMethodMetadata> feignMethodMetadataMap = new HashMap<>();
|
||||
|
||||
for (Map.Entry<DubboTransportedMethodMetadata, RestMethodMetadata> entry : feignRestMethodMetadataMap.entrySet()) {
|
||||
RestMethodMetadata feignRestMethodMetadata = entry.getValue();
|
||||
RequestMetadata feignRequestMetadata = feignRestMethodMetadata.getRequest();
|
||||
DubboRestServiceMetadata metadata = repository.get(serviceName, feignRequestMetadata);
|
||||
if (metadata != null) {
|
||||
DubboTransportedMethodMetadata dubboTransportedMethodMetadata = entry.getKey();
|
||||
Map<String, Object> dubboTranslatedAttributes = dubboTransportedMethodMetadata.getAttributes();
|
||||
Method method = dubboTransportedMethodMetadata.getMethod();
|
||||
GenericService dubboGenericService = dubboGenericServiceFactory.create(metadata, dubboTranslatedAttributes);
|
||||
RestMethodMetadata dubboRestMethodMetadata = metadata.getRestMethodMetadata();
|
||||
MethodMetadata methodMetadata = dubboTransportedMethodMetadata.getMethodMetadata();
|
||||
FeignMethodMetadata feignMethodMetadata = new FeignMethodMetadata(dubboGenericService,
|
||||
dubboRestMethodMetadata, feignRestMethodMetadata);
|
||||
feignMethodMetadataMap.put(method, feignMethodMetadata);
|
||||
}
|
||||
}
|
||||
|
||||
return feignMethodMetadataMap;
|
||||
}
|
||||
|
||||
private static <T> T cast(Object object) {
|
||||
return (T) object;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user