RepoPilot

How do their APIs compare?

About netflix/hystrix · 2 messages · last activity 8/12/2026

Question

How do their APIs compare?

RepoPilot

I can compare the two projects' core APIs based on what's in the retrieved data, though I should note that comparing "API design philosophy" between a fault-tolerance library and a dependency-injection library involves comparing quite different problem domains.

netflix/hystrix — Command-wrapping API

Hystrix's core usage pattern is subclassing a command object and invoking it through one of several execution styles. From the README:

public class CommandHelloWorld extends HystrixCommand<String> {
    private final String name;
    public CommandHelloWorld(String name) {
        super(HystrixCommandGroupKey.Factory.asKey("ExampleGroup"));
        this.name = name;
    }
    @Override
    protected String run() {
        return "Hello " + name + "!";
    }
}

[README.md:L56-L74]

Callers then choose synchronous, Future-based, or Observable-based invocation:

String s = new CommandHelloWorld("Bob").execute();
Future<String> s = new CommandHelloWorld("Bob").queue();
Observable<String> s = new CommandHelloWorld("Bob").observe();

[README.md:L79-L82]

This is an inheritance/wrapper-based API — you extend HystrixCommand<T>, override run(), and the base class handles circuit-breaking, isolation, and fallback logic.

On top of that imperative API, hystrix-javanica offers an annotation-driven alternative so you don't have to write command classes by hand — you annotate a method with @HystrixCommand and an AspectJ/Spring AOP aspect (HystrixCommandAspect) wraps the call [hystrix-contrib/hystrix-javanica/README.md:L1-L46]. It also layers in caching annotations like @CacheResult, @CacheRemove, and @CacheKey, where cache keys are derived either from annotated parameters or a designated cacheKeyMethod [hystrix-contrib/hystrix-javanica/src/main/java/com/netflix/hystrix/contrib/javanica/cache/annotation/CacheResult.java:L36-L49] [hystrix-contrib/hystrix-javanica/README.md:L487-L516].

square/dagger — Annotation-driven dependency injection API

Dagger's API is annotation-first from the start. Consumers declare dependencies with @Inject fields and wire them via @Module/@Provides classes, then bootstrap through ObjectGraph:

class TestApp implements Runnable {
  @Inject Foo foo;
  public static void main(String[] args) {
    ObjectGraph.create(new TestModule()).get(TestApp.class).run();
  }
  @Module(injects = TestApp.class)
  static class TestModule {
    @Provides Foo providesFoo(MyFoo foo) { return foo; }
  }
}

[compiler/src/it/same-provides-method-name/src/main/java/test/TestApp.java:L27-L57]

There's no runtime reflection-heavy proxying by default for the primary path — Dagger's compiler module generates adapter code at compile time (InjectAdapter, ModuleAdapter, etc.), documented via javadoc templates like GET_METHOD, GET_DEPENDENCIES_METHOD, and MODULE_TYPE [compiler/src/main/java/dagger/internal/codegen/AdapterJavadocs.java:L25-L45]. If generated adapters aren't found at runtime, FailoverLoader falls back to reflective equivalents (ReflectiveAtInjectBinding, ReflectiveStaticInjection) [core/src/main/java/dagger/internal/FailoverLoader.java:L16-L31].

Key contrasts

AspectHystrixDagger
Primary integration styleSubclass + override (HystrixCommand<T>)Field/constructor annotations (@Inject, @Provides, @Module)
Alternate styleAnnotation-based via javanica + AOP proxyN/A (annotations are the only style; codegen is transparent)
Concurrency model exposed in APIExplicit: execute(), queue(), observe() give sync/Future/ObservableNot concurrency-related; API is about graph construction and injection

Want to ask your own question?

Open chat for netflix/hystrix

Public Q&A. Generated by RepoPilot from the actual source of netflix/hystrix. AI answers can be incomplete or stale — verify before relying on them.