java dependency injection through code

What happened?

As always the detailed documentation provided earlier got outdated when the code evolved. The following is not much but it will be accurate at least. If something is not covered just ask me.

What it is

Dependency management through code. No XML. No Annotations. No code dependencies in the wrong direction. Application code is written as if there is no DI library. Indeed, this is the goal: wiring up the application had become so simple that no sophisticated library is needed to aid it. Silk will make sophisticated wiring easier until it is no longer needed and gracefully disappears as simplicity emerges.

Why it came to be

The classic struggle: How hard could it be to write something better than the so called “mature” crap mostly used in the enterprise? As often it turned out: not that complicated. More importantly: while the major players are all addictive frameworks the silk library is intended as a substitute that in the end gets rid of itself. Confused? It’s just saying: Small is beautiful. We don’t need a library for that. So I’m not using it.

Why use it?

If you have already decided to use a container you’re most likely better off with silk. It’s tiny, debuggable, straight forward stand alone library that makes common things easy and uncommon ones easy to add. However, it makes some strong decisions to keep dependency injection sane. Don’t fight them. Ask why. Learn.

How to use it

class RobotLegsProblem extends BinderModule {

	protected void declare() {
		construct( Robot.class );
		bind( left, Leg.class ).toConstructor();
		bind( right, Leg.class ).toConstructor();
		injectingInto( left, Leg.class ).bind( Foot.class ).to( left, Foot.class );
		injectingInto( right, Leg.class ).bind( Foot.class ).to( right, Foot.class );
Injector injector = Bootstrap.injector( RobotLegsProblem.class );
Robot robot = injector.resolve( dependency( Robot.class ) );

How to learn it

The tests for the binding API do illustrate what can be done and how to do it. It’s all ordinary code. Read it.

Not very handy but it doesn’t lie. A tour could be to look at

Looking at the other tests in the same folder will also be useful. There is more to discover. Most likely silk allows to do what you want. Otherwise just ask me for help.

How it works

At the core is a quite simple instance container. It consists of a list of injectrons sorted by precision (most precise first) that is assembled from bindings during initialization and then never changes again. Each injectron is a factory like typed source of instances. When a dependency is resolved the first injectorn that matches the requested dependency is asked to yield the instance for it. If the requested type is a 1-dimensional array and no injectorn specifically for that type exists, the resulting array is assembled from all matching element instance providers. That’s it.


Most of the library is just a utility build around the container. The fluent API is a utility to describe bindings (assemblies) to create a container from. Modules and bundles are utilities to organize and assemble sets of such bindings to allow configuration and customization during the bootstrapping of a container. Suppliers, repositories and scopes are abstractions to create and manage instances and their life-cycles. Providers and factories make this even more convenient. Finally actions utilize several features to build a input-processing-output abstraction onto methods.


Both dependencies (instance requirements) as well as injectrons (instance providers) are (also) data descriptions of what they require/provide. Such descriptions can be more or less specific or precise. A wild-card type is less precise than a fully specified one. A sub-class more specific than a super-class. A named instance more precise than a unnamed one, one specifically meant for a particular package or parent instance is again more precise than one that doesn’t specify these. There is no particular logic other than: the more we know about when/where something applies the more specific or precise it is. All in all it is fairly intuitive - one just needs to remember the sequence in which properties are compared: type, name, hierarchy, package.