~100KB · Zero overhead · Java 8+

Dependency injection
without the magic.

Configuration, constructor injection, and events in a tiny jar.
No proxies. No field injection. No framework lock-in.

What makes Pixie different

No Proxies

Your objects are real objects. Clean stack traces, full JVM speed, and GraalVM native-image friendly.

Properties or Code

Configure from key-value properties — maps to AWS SSM, K8s ConfigMaps, Consul. Or wire in plain Java.

Built-in Events

Fire with @Event Consumer<T>, observe with @Observes. Polymorphic dispatch and exception isolation.

No Lock-in

Every class works with new. Remove Pixie and your code still compiles. Safe for any team size.

Four Producers

Constructors, @Factory methods, @Builder patterns, or pre-built instances. Use what fits.

Type-Safe Generics

Handler<String, Integer> only matches implementations with those exact type arguments. Wildcards included.

public class ShoppingCart {

    public ShoppingCart(
            @Param("taxRate") final double taxRate,
            @Param("processor") @Component
                final PaymentProcessor processor,
            @Event
                final Consumer<OrderPlaced> event) {

        // Plain constructor. Works with new.
    }
}

Annotate a constructor.
Pixie does the rest.

@Param maps configuration values. @Component injects dependencies by type or name. @Event wires the event system. Your class stays plain Java.

All annotations →
cart = new://com.example.ShoppingCart
cart.taxRate = 0.08
cart.processor = @stripe

stripe = new://com.example.StripeProcessor
stripe.apiKey = sk_live_abc123
stripe.timeout = 30 seconds

Configure from properties
or in plain Java.

Key-value properties map directly to AWS Parameter Store, Kubernetes ConfigMaps, and every cloud platform. Component references use @name syntax. Or skip properties entirely and use System.builder().

Configuration guide →
// Factory — full control over construction
public class Connection {

    @Factory
    public static Connection create(
            @Param("url") final String url,
            @Param("timeout") @Default("30 seconds")
                final Duration timeout) {
        return new Connection(url, timeout);
    }
}

// Builder — for complex construction
public class Pipeline {

    @Builder
    public static PipelineBuilder builder() {
        return new PipelineBuilder();
    }
}

Four ways to
create components.

Constructors for simple cases. @Factory methods when you need validation or the constructor is private. @Builder for complex objects with many optional parameters. Or add pre-built instances with system.add().

Producer types →
// Fire events from any component
public class OrderService {

    public OrderService(
            @Event final Consumer<OrderPlaced> event) {
        this.event = event;
    }

    public void place(String id) {
        event.accept(new OrderPlaced(id));
    }
}

// Observe events — no registration needed
public class EmailReceipt {

    public void send(@Observes OrderPlaced e) {
        mailer.send(e.getId());
    }
}

Decouple with events.

Inject a Consumer<T> to fire events. Add @Observes to receive them. Polymorphic dispatch, before/after hooks, and exception isolation included. In tests, just pass a lambda — no framework needed.

Event system →
<dependency>
    <groupId>org.tomitribe.pixie</groupId>
    <artifactId>pixie</artifactId>
    <version>2.0</version>
</dependency>

Get started in seconds

One dependency. No transitive framework graph. No annotation processors. No code generation.

Installation guide →

Explore the docs