class CoffeeApp {
@Component interface CoffeeComponent {
CoffeeMaker coffeeMaker();
@Component.Builder interface Builder {
Builder logLevel(String logLevel);
CoffeeComponent buildComponent();
}
}
interface Logger {
void log(String msg);
}
static class CoffeeMaker {
private final Logger logger;
@Inject CoffeeMaker(Logger logger) {
this.logger = logger;
}
void brew() {
logger.log("~ ~ ~ heating ~ ~ ~");
logger.log("=> => pumping => =>");
logger.log(" [_]P coffee! [_]P ");
}
}
@Inject static Logger createLogger(String level) {
return msg -> System.out.println(level + " " + msg);
}
}This dependency injector uses the following annotations:
@Injectdeclares an injection point. It can be a constructor or a static method in the bean class. It can also be a static method in the component class.@Qualifierand its default implementation@Named.- And of course,
@Component,@Component.Factoryand@Component.Builder.
Note this is not a complete implementation of javax.inject or jakarta.inject, because:
Instead there's the following rule:
If two beans of the same type and same qualifier are injected by the same component, then they are the same instance.
Intuitively this means the same bean instance is injected everywhere (unless you're using qualifiers, or inject a provider).
If you want to re-use a bean instance across multiple components, or multiple instances of the same component, pass it via a @Factory or a @Builder.
If you inject Provider<TheBean> provider, calling provider.get() will create a fresh bean instance every time.
There are no "subcomponents" or "component dependencies".
There is no @Module.
There is no @Binds. Use a @Provides method.
There is no Provider. Create a factory if you need one.
There is no @IntoList or @IntoSet. Collections can be assembled in a @Provides method.
There is no @Lazy, @BindsInstance or @AssistedInject. I don't even know what these do.
- modular-thermosiphon (dagger's "coffee machine" demo)
- jbock uses it, see for example ValidateComponent