Skip to content

erwolff/novocaine

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

12 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Novocaine

Novocaine is a framework designed to make dependency injection simple. It works solely with the native javax.inject annotations and handles all of the standard use-cases for injection. Currently, Novocaine supports Constructor, Method, and Field injection strategies.

Supported Annotations

@Inject
@Named
@Qualifier
@Singleton

Example Usage

Let's assume we're wiring up a server. Our server uses a class called Runner to start everything up:

public class Runner {

    public static void main(String[] args) {
        Runner runner = new Runner();
        runner.run();
    }

    private void run() {
        // ...
    }
}

Consider a @Singleton service:

@Singleton
public class PaymentService {

    public void pay() {
        // ...
    }
}

We can now use Novocaine to inject this service into our Runner class (field injection demonstrated):

public class Runner {

    @Inject
    private PaymentService paymentService;

    public static void main(String[] args) {
        Runner runner = new Runner();
        runner.run();
    }

    private void run() {
        // pass Novocaine the top-level object and let it instantiate everything for us:
        Novocaine.inject(this)

        // paymentService is fully instantiated:
        paymentService.pay();
    }
}

Let's now assume that we have a few different means of paying in our PaymentService: we can pay with cash, credit, or debit. We'll use an interface to define how to pay, and use annotations to define our injection strategies.

First, the interface:

public interface Payment() {

    void pay();
}

For our cash payment, we'll simply write a concrete implementing class and inject it directly. Here's our cash implementation:

public class CashPaymentImpl implements Payment {

    @Override
    public void pay() {
        // pay with cash
    }
}

For our credit payment, we'll use a qualifier-based implementation. We'll need to create the custom annotation @CreditPayment and specify it as a qualifier:

@Retention(RetentionPolicy.RUNTIME)
@Qualifier
public @interface CreditPayment { }

Now we can annotate our concrete implementing class with this custom annotation:

@CreditPayment
public class CreditPaymentImpl implements Payment {

    @Override
    public void pay() {
        // pay with credit
    }
}

For our debit payment, we'll use a named-based implementation. We can simply add the @Named annotation with a value of debit to the top of our concrete implementing class:

@Named("debit")
public class DebitPaymentImpl implements Payment {

    @Override
    public void pay() {
        // pay with debit
    }
}

We're now ready to use these different payment methods in our PaymentService. We have many ways in which we can inject them. Let's go through each.

Constructor Injection
@Singleton
public class PaymentService {

    private Payment cashPayment;
    private Payment creditPayment;
    private Payment debitPayment;

    @Inject
    public PaymentService(CashPaymentImpl cashPayment,
                          @CreditPayment Payment creditPayment,
                          @Named("debit") Payment debitPayment) {
        this.cashPayment = cashPayment;
        this.creditPayment = creditPayment;
        this.debitPayment = debitPayment;
    }
}
Field Injection
@Singleton
public class PaymentService {

    @Inject
    private Payment cashPayment;

    @Inject
    @CreditPayment
    private Payment creditPayment;

    @Inject
    @Named("debit")
    private Payment debitPayment;

}
Method Injection
@Singleton
public class PaymentService {

    private Payment cashPayment;
    private Payment creditPayment;
    private Payment debitPayment;

    @Inject
    public void setCashPayment(CashPaymentImpl cashPayment) {
        this.cashPayment = cashPayment;
    }

    @Inject
    public void setCreditPayment(@CreditPayment Payment creditPayment) {
        this.creditPayment = creditPayment;
    }

    @Inject
    public void setDebitPayment(@Named("debit") Payment debitPayment) {
        this.debitPayment = debitPayment;
    }
}

About

Simple Dependency Injection

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Languages