HystrixMethodHandler extends MicroserviceMethodHandler { @Override public Object invoke(final Method method, final Object... args) throws Exception { String serviceName = getProxyBean().getMicroserviceName(); String methodName = method.getName(); MethodConfig methodConfig = serviceConfig.getMethodConfig(method); if (methodConfig == null) { methodConfig = serviceConfig.getDefaultConfig(); } if (method.getDeclaringClass() == Object.class || methodConfig == null || !methodConfig.isHystrixActive()) { return methodHandler.invoke(method, args); } Setter setter = methodConfig.getHystrixCommandSetter(); String cacheKey = createCacheKey(serviceName, methodName, methodConfig, args); Callable<Object> fallback = fallbackService != null ? () -> method.invoke(fallbackService, args) : null; HystrixCommand<Object> hystrixCommand = new Builder<>(setter, () -> methodHandler.invoke(method, args)) .cacheKey(cacheKey) .fallback(fallback) .ignoredExceptions(methodConfig.getIgnoredExceptions()) .build(); try { return hystrixCommand.execute(); } catch (HystrixBadRequestException ex) { throw unwrapException(ex); } } HystrixMethodHandler(final MicroserviceMethodHandler methodHandler);   HystrixMethodHandler(final MicroserviceMethodHandler methodHandler, final ServiceConfig serviceConfig); @Override Object invoke(final Method method, final Object... args); @Override MicroserviceProxyBean getProxyBean(); @Override InjectionPoint getInjectionPoint();  }
@Test public void testInvokeDefault() throws Exception { MethodConfig methodConfig = MethodConfig.createBuilder(SERVICE_NAME, BEAN_NAME + ":" + FIELD_NAME).build(); ServiceConfig serviceConfig = new ServiceConfig(methodConfig); HystrixMethodHandler hystrixMethodHandler = new HystrixMethodHandler(parentMethodHandler, serviceConfig); Method method = UnstableMicroservice.class.getMethod("fail"); Mockito.when(parentMethodHandler.invoke(method)).thenThrow(new FailingCallException()); assertThatThrownBy(() -> hystrixMethodHandler.invoke(method)) .isInstanceOf(FailingCallException.class); }
@Test public void testInvokeObjectMethod() throws Exception { MethodConfig methodConfig = MethodConfig.createBuilder(SERVICE_NAME, BEAN_NAME + ":" + FIELD_NAME) .hystrixActive(true) .build(); ServiceConfig serviceConfig = new ServiceConfig(methodConfig); HystrixMethodHandler hystrixMethodHandler = new HystrixMethodHandler(parentMethodHandler, serviceConfig); Method method = UnstableMicroservice.class.getMethod("toString"); Mockito.when(parentMethodHandler.invoke(method)).thenThrow(new FailingCallException()); assertThatThrownBy(() -> hystrixMethodHandler.invoke(method)) .isInstanceOf(FailingCallException.class); }
@Test public void testInvokeCircuitBreaker() throws Exception { MethodConfig methodConfig = MethodConfig.createBuilder(SERVICE_NAME, BEAN_NAME + ":" + FIELD_NAME) .hystrixActive(true) .commandProperty(CommandProperties.CIRCUIT_BREAKER_ENABLED, Boolean.TRUE.toString()) .build(); ServiceConfig serviceConfig = new ServiceConfig(methodConfig); HystrixMethodHandler hystrixMethodHandler = new HystrixMethodHandler(parentMethodHandler, serviceConfig); Method method = UnstableMicroservice.class.getMethod("fail"); Mockito.when(parentMethodHandler.invoke(method)).thenThrow(new FailingCallException()); assertThatThrownBy(() -> hystrixMethodHandler.invoke(method)) .isInstanceOf(HystrixRuntimeException.class) .hasMessageContaining("failed"); }
@Test public void testInvokeTimeout() throws Exception { MethodConfig methodConfig = MethodConfig.createBuilder(SERVICE_NAME, BEAN_NAME + ":" + FIELD_NAME) .hystrixActive(true) .commandProperty(CommandProperties.EXECUTION_TIMEOUT_ENABLED, Boolean.TRUE.toString()) .build(); ServiceConfig serviceConfig = new ServiceConfig(methodConfig); HystrixMethodHandler hystrixMethodHandler = new HystrixMethodHandler(parentMethodHandler, serviceConfig); Method method = UnstableMicroservice.class.getMethod("timeout"); Mockito.when(parentMethodHandler.invoke(method)).thenAnswer(a -> method.invoke(UnstableMicroservice.class)); assertThatThrownBy(() -> hystrixMethodHandler.invoke(method)) .isInstanceOf(HystrixRuntimeException.class) .hasMessageContaining("timed-out"); }
@Test public void testInvokeRequestCachingParameters() throws Exception { MethodConfig methodConfig = MethodConfig.createBuilder(SERVICE_NAME, BEAN_NAME + ":" + FIELD_NAME) .hystrixActive(true) .cacheKeyParameterIndex(1) .commandProperty(CommandProperties.REQUEST_CACHE_ENABLED, Boolean.TRUE.toString()) .build(); ServiceConfig serviceConfig = new ServiceConfig(methodConfig); HystrixMethodHandler hystrixMethodHandler = new HystrixMethodHandler(parentMethodHandler, serviceConfig); Method method = UnstableMicroservice.class.getMethod("add", int.class, int.class); Mockito.when(parentMethodHandler.invoke(Mockito.any(), Mockito.any(), Mockito.any())) .thenAnswer(answer -> method.invoke(UnstableMicroservice.class, (Integer) answer.getArgument(1), (Integer) answer.getArgument(2))); hystrixMethodHandler.invoke(method, 1, 1); hystrixMethodHandler.invoke(method, 1, 2); hystrixMethodHandler.invoke(method, 2, 1); Mockito.verify(parentMethodHandler, Mockito.times(1)).invoke(method, 1, 1); Mockito.verify(parentMethodHandler, Mockito.times(1)).invoke(method, 1, 2); Mockito.verify(parentMethodHandler, Mockito.times(0)).invoke(method, 2, 1); }