标题通过 反射实现方法调用的统一转发
目的:当请求到来时,通过切面和注解的方式 将方法的调用目的地转发到目标方法:
//此为转发调用的核心方法
@Service
@Transactional(rollbackFor = Exception.class)
public class ControlCenterApiServiceImpl implements ControlCenterApiService {
//doLog为记录日志的,可以不用关注
@Override
public Object invoke(ControlCenterRequest request) {
String uri = request.getUri();
String clazzUri = uri.substring(0, uri.lastIndexOf(":"));
String methodUri = uri.substring(uri.lastIndexOf(":") + 1);
Object invoke = null;
Set<Map.Entry<String, Object>> entries = SpringUtils.getContext().getBeansWithAnnotation(CenterUri.class).entrySet();
for (Map.Entry<String, Object> entry : entries) {
Object value2 = entry.getValue();
Class<?> aClass = value2.getClass();
Class<?> userClass = ClassUtils.getUserClass(aClass);
CenterUri annotation = userClass.getAnnotation(CenterUri.class);
String value = annotation.value();
if (value.equals(clazzUri)) {
Method[] declaredMethods = userClass.getDeclaredMethods();
for (Method method : declaredMethods) {
if (method.isAnnotationPresent(CenterUri.class)) {
CenterUri methodAn = method.getAnnotation(CenterUri.class);
if (ObjectUtils.isEmpty(methodAn)) {
continue;
}
String value1 = methodAn.value();
if (value1.equals(methodUri)) {
long start = System.currentTimeMillis();
try {
Object executeTarget = SpringUtils.getBeanByType(Class.forName(userClass.getName()));
// executeTarget = userClass.getConstructor().newInstance();
invoke = method.invoke(executeTarget, request);
long end = System.currentTimeMillis();
Long consuming = end - start;
doLog(request, JsonUtils.toJson(invoke), true, true, 0, method.getName(), consuming);
return invoke;
} catch (ClassNotFoundException | IllegalAccessException | InvocationTargetException | RuntimeException e) { //NoSuchMethodException | InstantiationException |
long end = System.currentTimeMillis();
Long consuming = end - start;
doLog(request, JsonUtils.toJson(invoke), false, false, 0, method.getName(), consuming);
throw new BizException(ControlCenterErrorEnum.INTERFACE_INVOKE_ERROR, ControlCenterErrorEnum.INTERFACE_INVOKE_ERROR.getDesc());
}
}
}
}
}
}
ObjectResult<Object> responseData = new ObjectResult<>();
responseData.setSuccess(false);
responseData.setMessage(request.getUri() + "请求失败");
return responseData;
}
//此注解类似于我们使用到的postMapping注解和GetMapping注解
@Target({ElementType.METHOD,ElementType.TYPE})
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Inherited
public @interface CenterUri {
String value();
}
CenterUri 的使用方式如下:
@Slf4j
@Service
@Transactional(rollbackFor = Exception.class)
@CenterUri("mom")
public class MomApiServiceImpl implements MomApiService {
@Override
@CenterUri("submitEqptAlive")
public ObjectResult submitEqptAlive(ControlCenterRequest request)
理论输出:
当我们在调用由@CenterUri注解标注的类中的方法时,invoke会根据方类和方法上的注解的value值来判定要请求的方法时哪个,并将参数转发至要调用的方法形参中;然后执行上面的invoke方法来实现方法的转发调用
调用方式:
@Override
public ObjectResult wmsCommitInventoryStatusToErpRequest(List<CommitInventoryStatusDetailRequest> data) {
Map<String, Object> ccapiParam = new HashMap<>();
ControlCenterRequest ccapiRequest = new ControlCenterRequest();
ccapiRequest.setHouseCode(LesConfig.houseCode);
ccapiRequest.setSystemCode(LesConfig.systemCode);
ccapiRequest.setParams(ccapiParam);
ccapiRequest.setUri("erp:inventoryStatus");
ObjectResult ccapiResponse = (ObjectResult) controlCenterApiService.invoke(ccapiRequest);
return ccapiResponse;
}
以上代码只通过invoke的调用即可请求到目标执行方法