Feign调用转成本地方法调用
Feign调用转成本地方法调用
最后更新于
Feign调用转成本地方法调用
最后更新于
private Map<String /** url **/, Map.Entry<HandlerMethod, Set<RequestMethod>>> parseServiceBHandlerMethodMapping() {
if (servletContext == null) {
return new HashMap<>();
}
final Map<String /** url **/, Map.Entry<HandlerMethod, Set<RequestMethod>>> handlerMethodMapping = new HashMap<>();
WebApplicationContext webContext = WebApplicationContextUtils.getWebApplicationContext(servletContext);
Map<String, HandlerMapping> allRequestMappings = BeanFactoryUtils.beansOfTypeIncludingAncestors(webContext,
HandlerMapping.class, true, false);
if (allRequestMappings.size() == 0) {
return handlerMethodMapping;
}
for (HandlerMapping handlerMapping : allRequestMappings.values()) {
if (!(handlerMapping instanceof RequestMappingHandlerMapping)) {
continue;
}
RequestMappingHandlerMapping requestMappingHandlerMapping = (RequestMappingHandlerMapping) handlerMapping;
Map<RequestMappingInfo, HandlerMethod> handlerMethods = requestMappingHandlerMapping.getHandlerMethods();
for (Map.Entry<RequestMappingInfo, HandlerMethod> entry : handlerMethods.entrySet()) {
HandlerMethod handlerMethod = entry.getValue();
// 这里只处理ServiceB 包路径下的controller
if (!handlerMethod.getMethod().getDeclaringClass().getName().contains(".serviceB.")) {
continue;
}
// 这里只针对加上了@LocalCall注解的方法去解析,有些方法依赖http上下文,不能直接转为本地方法调用
if (handlerMethod.getMethodAnnotation(LocalCall.class) == null) {
continue;
}
RequestMappingInfo requestMappingInfo = entry.getKey();
if (CollectionUtils.isEmpty(requestMappingInfo.getDirectPaths())) {
continue;
}
Set<RequestMethod> requestMethodSet = requestMappingInfo.getMethodsCondition().getMethods();
if (CollectionUtils.isEmpty(requestMethodSet)) {
continue;
}
log.info("parseServiceBHandlerMethodMapping, urls={}, request_methods={}, method={}",
requestMappingInfo.getDirectPaths(),
requestMappingInfo.getMethodsCondition().getMethods(),
handlerMethod.getMethod());
for (String url : requestMappingInfo.getDirectPaths()) {
// URL_PREFIX实际是ServiceA的context-path
handlerMethodMapping.put(URL_PREFIX + url, new AbstractMap.SimpleImmutableEntry(handlerMethod, requestMethodSet));
}
}
}
return handlerMethodMapping;
}public void onApplicationEvent(ApplicationStartedEvent event) {
Map<String /** url **/, Map.Entry<HandlerMethod, Set<RequestMethod>>> handlerMethodMapping = parseServiceBHandlerMethodMapping();
if (handlerMethodMapping.size() == 0) {
return;
}
Class<?> clazz;
try {
clazz = Class.forName("ServiceBFeignClient class name");
} catch (ClassNotFoundException e) {
return;
}
Method[] methods = clazz.getMethods();
if (methods.length == 0) {
return;
}
for (Method method : methods) {
HandlerMethod handlerMethod = getHandlerMethod(handlerMethodMapping, method);
if (handlerMethod == null) {
continue;
}
// 缓存下来,后面直接用
METHOD_MAPPING.put(method, handlerMethod);
}
}
private HandlerMethod getHandlerMethod(Map<String /** url **/, Map.Entry<HandlerMethod, Set<RequestMethod>>> urlMapping, Method method) {
Map.Entry<String[] /** url **/, RequestMethod[]> entry = parseMethodInfo(method);
if (entry == null) {
return null;
}
Map.Entry<HandlerMethod, Set<RequestMethod>> mappingEntry = urlMapping.get(entry.getKey()[0]);
if (mappingEntry == null) {
return null;
}
// RequestMethod也要可以匹配才行
if (Arrays.stream(entry.getValue()).anyMatch(o -> mappingEntry.getValue().contains(o))) {
log.info("getHandlerMethod, method={}, controller_method={}",
method, mappingEntry.getKey().getMethod());
return mappingEntry.getKey();
}
return null;
}
/**
* 方法比较简单,就是解析注解拿到url和RequestMethod
*/
private Map.Entry<String[], RequestMethod[]> parseMethodInfo(Method method) {
RequestMapping requestMapping = method.getAnnotation(RequestMapping.class);
if (requestMapping != null) {
String[] urls = requestMapping.value();
if (urls.length == 0) {
return null;
}
RequestMethod[] requestMethods = requestMapping.method();
if (requestMethods.length == 0) {
return null;
}
return new AbstractMap.SimpleImmutableEntry<>(urls, requestMethods);
}
GetMapping getMapping = method.getAnnotation(GetMapping.class);
if (getMapping != null) {
String[] urls = getMapping.value();
if (urls.length == 0) {
return null;
}
return new AbstractMap.SimpleImmutableEntry<>(urls, new RequestMethod[]{RequestMethod.GET});
}
PostMapping postMapping = method.getAnnotation(PostMapping.class);
if (postMapping != null) {
String[] urls = postMapping.value();
if (urls.length == 0) {
return null;
}
return new AbstractMap.SimpleImmutableEntry<>(urls, new RequestMethod[]{RequestMethod.POST});
}
return null;
}
@Pointcut("execution(* ServiceBFeignClient.*(..))")
public void pointcut() {
}
@Around(value = "pointcut()")
public Object doAround(ProceedingJoinPoint pjp) throws Throwable {
if (enableLocalCall()) {
Method method = ((MethodSignature) pjp.getSignature()).getMethod();
HandlerMethod handlerMethod = METHOD_MAPPING.get(method);
if (handlerMethod != null) {
log.info("doAround, method={}, controller_method={}, args={}",
method, handlerMethod.getMethod(), pjp.getArgs());
// 拿到对应的Controller
Object obj = applicationContext.getBean(handlerMethod.getBeanType());
// 放射调用
return handlerMethod.getMethod().invoke(obj, pjp.getArgs());
}
}
return pjp.proceed();
}
private boolean enableLocalCall() {
// 开关控制AOP是否实时生效
return propertyHelper.getPropertyBoolean("aop switch key");
}