Lightweight dependency injection for Java and Android (JSR-330)

Overview

About Feather

Feather is an ultra-lightweight dependency injection (JSR-330) library for Java and Android. Dependency injection frameworks are often perceived as "magical" and complex. Feather - with just a few hundred lines of code - is probably the easiest, tiniest, most obvious one, and is quite efficient too (see comparison section below).

<dependency>
    <groupId>org.codejargon.feather</groupId>
    <artifactId>feather</artifactId>
    <version>1.0</version>
</dependency>

Javadoc for Feather

Usage - code examples
Create Feather (the injector)
Feather feather = Feather.with();

An application typically needs a single Feather instance.

Instantiating dependencies

Dependencies with @Inject constructor or a default constructor can be injected by Feather without the need for any configuration. Eg:

public class A {
    @Inject
    public A(B b) {
        // ...
    }
}

public class B {
    @Inject
    public B(C c, D d) {
        // ...
    }
}

public class C {}

@Singleton
public class D {
    // something expensive or other reasons for being singleton
}

Creating an instance of A:

A a = feather.instance(A.class);
Providing additional dependencies to Feather

When injecting an interface, a 3rd party class or an object needing custom instantiation, Feather relies on configuration modules providing those dependencies:

public class MyModule {
    @Provides
    @Singleton // an app will probably need a single instance 
    DataSource ds() {
        DataSource dataSource = // instantiate some DataSource
        return dataSource;
    }
}

Setting up Feather with module(s):

Feather feather = Feather.with(new MyModule());

The DataSource dependency will now be available for injection:

public class MyApp {
    @Inject 
    public MyApp(DataSource ds) {
        // ...
    }
}

Feather injects dependencies to @Provides methods aguments. This is particularly useful for binding an implementation to an interface:

public interface Foo {}

public class FooBar implements Foo {
    @Inject
    public FooBar(X x, Y y, Z z) {
        // ...
    }
}

public class MyModule {
    @Provides
    Foo foo(FooBar fooBar) {
        return fooBar;
    }
}

// injecting an instance of Foo interface will work using the MyModule above:
public class A {
    @Inject
    public A(Foo foo) {
        // ...
    }
}

Note that the @Provides method serves just as a binding declaration here, no manual instantiation needed

Qualifiers

Feather supports Qualifiers (@Named or custom qualifiers)

public class MyModule {
    @Provides
    @Named("greeting")
    String greeting() {
        return "hi";
    }
        
    @Provides
    @SomeQualifier
    Foo some(FooSome fooSome) {
        return fooSome;
    };
}

Injecting:

public class A {
    @Inject
    public A(@SomeQualifier Foo foo, @Named("greeting") String greet) {
        // ...
    }
}

Or directly from feather:

String greet = feather.instance(String.class, "greeting");
Foo foo = feather.instance(Key.of(Foo.class, SomeQualifier.class));
Provider injection

Feather injects Providers to facilitate lazy loading or circular dependencies:

public class A {
    @Inject
    public A(Provider<B> b) {
        B b = b.get(); // fetch a new instance when needed
    }
}

Or getting a Provider directly from Feather:

Provider<B> bProvider = feather.provider(B.class);
Override modules
public class Module {
    @Provides
    DataSource dataSource() {
        // return a mysql datasource
    }
    
    // other @Provides methods
}

public class TestModule extends Module {
    @Override
    @Provides
    DataSource dataSource() {
        // return a h2 datasource
    }
}
Field injection

Feather supports Constructor injection only when injecting to a dependency graph. It inject fields also if it's explicitly triggered for a target object - eg to facilitate testing. A simple example with a junit test:

public class AUnitTest {
    @Inject
    private Foo foo;
    @Inject
    private Bar bar;

    @Before
    public void setUp() {
        Feather feather = // obtain a Feather instance
        feather.injectFields(this);
    }
}
Method injection

Not supported. The need for it can be generally avoided by a Provider / solid design (favoring immutability, injection via constructor).

Android example
class ExampleApplication extends Application {
    private Feather feather;

    @Override public void onCreate() {
        // ...
        feather = Feather.with( /* modules if needed*/ );
    }

    public Feather feather() {
        return feather;
    }
}

class ExampleActivity extends Activity {
    @Inject
    private Foo foo;
    @Inject
    private Bar bar;

  @Override public void onCreate(Bundle savedState) {
    // ...
    ((ExampleApplication) getApplication())
        .feather()
            .injectFields(this);
  }
}

For best possible performance, dependencies should be immutable and @Singleton. See full example in android-test.

Footprint, performance, comparison

Small footprint and high performance is in Feather's main focus.

  • compared to [Guice] (https://github.com/google/guice "Guice"): 1/50 the library size, ~10x startup speed
  • compared to Dagger: 1/4 the library size (of just Dagger's run-time part), ~2x startup speed

Note: startup means creation of the container and instantiation of an object graph. Executable comparison including Spring, Guice, Dagger, PicoContainer is in 'performance-test' module.

How it works under the hood

Feather is based on optimal use of reflection to provide dependencies. No code generating, classpath scanning, proxying or anything costly involved.

A simple example with some explanation:

class A {
    @Inject
    A(B b) {

    }
}

class B {

}

Without the use of Feather, class A could be instantiated with the following factory methods:

A a() {
    return new A(b());
}

B b() {
    return new B();
}

Most of the information in these factories are redundant and they tend to be hot spots for changes and sources for merge hells. Feather avoids the need for writing such factories - by doing the same thing internally: When an instance of A is injected, Feather calls A's constructor with the necessary arguments - an instance of B. That instance of B is created the same way - a simple recursion, this time with no further dependencies - and the instance of A is created.

Comments
  • @PostConstruct

    @PostConstruct

    Just a small question: Is it true, that this part of JSR330 is simply not implemented yet? I just started to add the web integration part of dinistiq and the modules stuff from the Google Guice integration of a web framework of mine, since you are using a similar modules approach, to obtain all the functionality I would need from a small DI solution.

    Besides that missing bit, the JSR330 feather looks quite promising to get the whole thing up and running.

    opened by mgoellnitz 2
  • How to instantiate a class which takes custom parameters?

    How to instantiate a class which takes custom parameters?

    I want to instantiate a Logger by passing a class to it and injecting the logger into another instance crated through other means but the documentation isn't clear on that.

    opened by SharkFourSix 0
  • Would Feather work with Kotlin classes?

    Would Feather work with Kotlin classes?

    Hi. Hope all is well.

    I'm thinking of using Feather to implement DI under a test project using ktor. I'm just wondering if there might be any obvious pitfalls to watch out for. For example, in Spring Boot, most @Component classes need to be declared as open if they are written in Kotlin in order for Spring to be able to create proxies for them.

    Thanks for the framework! :+1:

    opened by jjzazuet 0
  • Compile at JDK 1.6

    Compile at JDK 1.6

    Hello, looking to use feather in a legacy project of mine and unfortunately we won't be upgrading to JDK 1.8 until later this year and am currently stuck on JDK 1.6 for the time being.

    I noticed in the project you are compiling at JDK 1.7 and when I cloned the project and built it locally it seems to work fine for JDK 1.6.

    Is it possible to change these in the root pom: <maven.compiler.source>1.6</maven.compiler.source> <maven.compiler.target>1.6</maven.compiler.target>

    opened by mbazos 0
  • Bug: inject or instantiate Feather class does not work

    Bug: inject or instantiate Feather class does not work

    Hello feather team,

    your DI framework fits very well for my use case. But unfortunately there is a bug which makes it unusable for me.

    Could you please fix this issue?! Thank you.

    import org.codejargon.feather.Feather;
    import org.codejargon.feather.Provides;
    import org.junit.Test;
    
    import static org.codejargon.feather.Feather.with;
    import static org.junit.Assert.assertEquals;
    
    public class FeatherTest {
    
        @Test
        public void injectFeatherShouldWork() {
            Feather feather = with(new Object() {
                @Provides
                public String createString(Feather feather) {
                    return feather.toString();
                }
            });
    
            assertEquals(feather.toString(), feather.instance(String.class));
        }
    
        @Test
        public void instantiateFeatherShouldWork() {
            Feather feather = with();
            assertEquals(feather, feather.instance(Feather.class));
        }
    
    }
    

    Best regards, Stefan

    opened by sealor 0
Releases(1.0)
Owner
Zsolt Herpai
Zsolt Herpai
JayWire Dependency Injection

JayWire Dependency Injection A very small and lightweight dependency injection framework for Java 8 without magic. Main features are: 100% pure Java c

VanillaSource 52 Jul 13, 2022
Dynamic Context Dependency Injection

Welcome to the Project Dynamic CDI JDK Informations Actual version is running from JDK8 up to JDK13. The version 1.0.x is based on JDK8. The implement

Sven Ruppert 8 Dec 10, 2019
A fast dependency injector for Android and Java.

Dagger A fast dependency injector for Java and Android. Dagger is a compile-time framework for dependency injection. It uses no reflection or runtime

Google 16.9k Dec 30, 2022
Netflix, Inc. 809 Dec 28, 2022
Xposed Injector by Saygus, and project fixed by Spring Musk

Xposed Injector Xposed Injector to mod games externally. Made by Saygus, and project fixed by Spring Musk. Spring Musk requested me to upload his proj

Menu Modder 10 Nov 1, 2022
Backport of functionality based on JSR-310 to Java SE 6 and 7. This is NOT an implementation of JSR-310.

ThreeTen backport project JSR-310 provides a new date and time library for Java SE 8. This project is the backport to Java SE 6 and 7. See the main ho

ThreeTen 541 Jan 8, 2023
Guice (pronounced 'juice') is a lightweight dependency injection framework for Java 6 and above, brought to you by Google.

Guice Latest release: 5.0.1 Documentation: User Guide, 5.0.1 javadocs, Latest javadocs Continuous Integration: Mailing Lists: User Mailing List Licens

Google 11.7k Dec 29, 2022
A light-weight and dynamic dependency injection framework

⚠️ This project is now part of the EE4J initiative. This repository has been archived as all activities are now happening in the corresponding Eclipse

Java EE 105 Dec 23, 2022
Yet another Java annotation-based command parsing library, with Dependency Injection inspired by Guice

Commander A universal java command parsing library Building This project uses Gradle. Clone this repository: git clone https://github.com/OctoPvP/Comm

OctoDev 4 Oct 2, 2022
JayWire Dependency Injection

JayWire Dependency Injection A very small and lightweight dependency injection framework for Java 8 without magic. Main features are: 100% pure Java c

VanillaSource 52 Jul 13, 2022
Spring Kurulumundan Başlayarak, Spring IOC ve Dependency Injection, Hibernate, Maven ve Spring Boot Konularına Giriş Yapıyoruz.

Spring Tutorial for Beginners File Directory Apache Tomcat Apache Tomcat - Eclipse Bağlantısı Spring Paketlerinin İndirilmesi ve Projeye Entegrasyonu

İbrahim Can Erdoğan 11 Apr 11, 2022
Dynamic Context Dependency Injection

Welcome to the Project Dynamic CDI JDK Informations Actual version is running from JDK8 up to JDK13. The version 1.0.x is based on JDK8. The implement

Sven Ruppert 8 Dec 10, 2019
JavaFX micro-framework that follows MVVM Pattern with Google Guice dependency Injection

ReactiveDeskFX (JavaFX and Google Guice MVVM Pattern micro-framework) JavaFX micro-framework to develop very fast JavaFX components with minimal code

TangoraBox 3 Jan 9, 2022
A lightweight, mixin like injection lib using ASM

ClassTransform A lightweight, mixin like injection lib using ASM. The usage is like Mixins. You can almost copy-paste mixins code and it works. Why? I

Lenni0451 15 Dec 22, 2022
A fast dependency injector for Android and Java.

Dagger A fast dependency injector for Java and Android. Dagger is a compile-time framework for dependency injection. It uses no reflection or runtime

Google 16.9k Dec 30, 2022
Android Auto Apps Downloader (AAAD) is an app for Android Phones that downloads popular Android Auto 3rd party apps and installs them in the correct way to have them in Android Auto.

Android Auto Apps Downloader (AAAD) is an app for Android Phones that downloads popular Android Auto 3rd party apps and installs them in the correct way to have them in Android Auto.

Gabriele Rizzo 865 Jan 2, 2023
Sauron, the all seeing eye! It is a service to generate automated reports and track migrations, changes and dependency versions for backend services also report on known CVE and security issues.

SAURON - VERSION AND DEPLOYMENT TRACKER DESCRIPTION Sauron, the all seeing eye! It is a service to generate automated reports and track migrations, ch

FREENOWTech 20 Oct 31, 2022
A injection client for Minecraft 1.8.9forge,forked and optimize on VapuLite

A injection client for Minecraft 1.8.9forge,forked and optimize on VapuLite

James_ 9 May 8, 2022
A free injection hacked client for Minecraft using Java-agents

Swift Swift is a free and open-source injection hacked client base for Minecraft using Java-agents. Issues If you notice any bugs, you can let us know

static final 36 Oct 8, 2022