Restx factory is a super fast components factory / dependency injection container, based on annotation processing and Java 6 service loader.
See the FAQ for details on the why and what.
See the vocabulary sections for general concepts and vocabulary used within restx factory.
Declaring a component using
The simplest way to declare a component is by using the
This will generate the corresponding machine and machine engine and declare it to the factory.
Named components injection with
You can use the
@javax.inject.Named annotation to specify the name of a dependency to be injected, or the name of component you define.
Declaring a component using
If constructor injection is not enough, you can use the module and its provider methods feature:
In this case the methods annotated with
@Provides are used to build components of their returned types. You can annotate them with
@Named to indicate the name of the component produced.
The provider methods can take arbitrary parameters, which are satisfied the same way as constructor parameters are injected (so you can use @Named to indicate their names).
@Named component is of type
Optional, it will be considered an
Optional<T> dependency of type T.
In this case, if the component is not found, Dependency Injection will not break with an exception, and
Optional.absent() will be injected.
It can be useful in particular cases, to handle loaded dependencies at runtime.
Following example will provide either jetty, simple or tomcat server depending on which
@Component of type
is found in the classpath :
The factory is able to inject all the components implementing a class or interface, you just need to use one of these types:
Deactivating a component
If a component is supposed to be available (eg because you load machines from the serviceloader and it is defined there) and you don’t want to actually have it (eg because it’s a filter that you don’t want to use in your app for performance or security reasons), you can deactivate the component by setting a String component (eg with
System.setProperty) on the activation key with the value
The activation key has the following form:
Note that by default (when not specified with
@Named the component name is the the type simple name if declared as a
@Component, or the provides method name if declared with
So if for instance you want to deactivate RESTX Cookies based session management, you can simply call:
Getting a Factory
Here is a simple way to build a Factory:
or even simpler:
This factory will load the machines declared in the
META-INF/services/restx.factory.FactoryMachine files, using the standard ServiceLoader mechanism. But don’t worry, you don’t have to write these files manually, restx factory annotation processing can do it for you!
Most of the time you won't need to create a Factory yourself. If you want to have access to the Factory in a component, declare it as a parameter in your injectable constructor and current factory will be injected into your component. But even that shold be used with care, because in this case the Factory won't have proper dependency tracking of your component.
Getting a component from the factory
Getting one component by type (raises an exception if not available or several components available):
Getting the list of components of a particular type:
Getting one component by name (raises an exception if not available):
Getting one component by type (note the use of
Optional from guava, to indicate it may not find anything):
This returns an optional named component (meaning that you also get its name). You can easily get the component itself:
Getting all components of a particular type:
Getting one component by name:
Defining a component alternative
Sometimes you want to define an alternative to some component that should replace the default component only under some circonstances. For instance if you want a specific component in dev mode, or have different implementations of a service which you would like to select at runtime only depending on your environment.
To do so restx factory uses a concept of alternative, which can be activated depending on the value of a string component in the factory.
Here is an example:
In this case the component
DevRestxSpecRepository is an alternative to
RestxSpecRepository, which should be activated only when a String component named
restx.mode has the value
Defining a component alternative Tip
If activating a component alternative based ona string component doesn’t seem enough for you, first consider using the
@Provides mechanism to put a string component in the factory depending on more complex elements, and then using this string component to activate your alternative.
For instance, if you want to activate an alternative based on the content of a file in your filesystem, you could do something like this:
And then define your alternative like this:
Defining a component customizer
To customize components produced in the factory before they are stored in the warehouse and returned to queries, you just need to provide a component implementing
ComponentCustomizerEngine or subclassing/using one of its implementation classes.
Here is an example:
Overriding a component produced by another machine
Overriding other machines is easy: all you need to is define your component with the same
restx.factory.Name, in a machine with more priority.
Machines being ordered by order of priority in ascending order, lower priorities override higher priorities. The priority by default is 0, so usually you override with a negative priority.
Beware that a
Name is composed of the name as a string, and a class. So to override a component you need to produce it as a NamedComponent with the exact same
Declaring a machine using
You can declare a whole machine using the
@Machine annotation. You shouldn’t use it too often since it’s more complex than other options, but it opens a lot of possibilities:
In the end the only thing that this annotation does is declare the machine in the
META-INF/restx.factory.FactoryMachine service loader file.
Defining a component alternative programmatically (advanced)
If you hit a wall with the simplistic approach to alternatives restx factory provides, it may be interesting to know how restx implement alternatives. The concept behind alternatives in restx is actually more powerful: restx factory supports factory of factory. So you can define a factory which builds other factories, then these factories will be available to build other components. An because when building other factory you can query the factory to find other components, you can take decisions based on the state of the factory.
One thing to remember when you do that is that restx will evaluate the conditions at factory load time (ie startup time in production).
As an example, here is the code generated when you use the
Restx factory borrows its vocabulary from factory and warehousing industry.
The factory is the main unit of component production. You usually have only one factory. It is composed of a list of machines and one warehouse.
A machine is a core unit of production inside the factory. It can be used to produce different kind of components, generally sharing the same functional concepts. It is itself composed of machine engines.
A machine engine is the smallest production unit. It is used to produce a single kind of components. This is the unit responsible to describe the Bill Of Materials (BOM) to build a component, and also responsible for building component boxes once the BOM is satisfied.
A machine engine does not produce component directly, but it produces boxes. These boxes are put in the warehouse by the factory. A box can contain a limited number of components, or be boundless (which corresponds to a singleton scope).
Component Customizer Engine and Component Customizer
A component customizer engine can be used to create customizers for particular components produced in the factory. The customization is applied whenever a component is produced by the machine engine, before the component box is stored in the warehouse.
The warehouse is where the component boxes are stored once they have been produced by an engine. The factory always check the warehouse first when you query for a component. The warehouse can be queried for components, if you just want to get a component without creating it if it’s not already built.
Why yet another dependency injection engine?
We wanted a compile time oriented dependency injection engine, mostly to get blazing fast engine startup. A hundred ms for the engine startup itself is already too slow in our metrics.
We tried dagger from the amazing guys from Square, but we were stuck with limitations, especially the lack of querying mecanisms in the container (dagger needed to know all the dependency injection roots at the time we investigated).
Therefore, and because writing a small DI engine is no rocket science, we decided to write our own.
restx factory supports only 2 types of injections:
- constructor injection
- provider method parameter injection (see
Yes, you read it correctly, no setter injection, no field injection.
The advantage of constructor injection is that all depedencies are clearly expressed, and you can make your objects immutable, and doesn’t require reflection to access the fields.
Besides injection, restx factory supports component customization, allowing you to customize a component after it is created and before it is delivered to other components / callers.
Annotation processor based
Despite you can use the factory without annotation processing, it shines when the injection code is generated by the provided annotation processor. Having generated code for that means that you can use your IDE to view the callers of your constructor, and better understand how the dependencies are satisfied.
Each component dependencies are expressed in what is called a Bill Of Material (BOM). It means that the container can analyze all the BOMs without actually instantiating the components. It means that you have very fast failure at startup in case of missing dependencies, and that we can isolate component instantiation times so that you know which component is wasting your startup time.
The container can be queried for components by class or by names. More query types could easily be added. These queries are also what is used to express the dependencies.
You can easily register component customizers which can be used to customize components produced by the factory. This allow contributions to or transformation of components, which is very useful for decoupling and plugins.
You can easily declare components which are made available to the factory only under some conditions.
Factory of Factory
You can define a factory machine which in turns builds other factory machines. This is the mechanism used under the hood to provide the alternatives support.
Support for Optional
By default all dependencies are mandatory, but you can use an
Optional<MyType> to express an optional dependency
The factory is able to inject all the components implementing a class or interface.
Easy component deactivation
Any component can easily be deactivated, ie marked as if it was not defined at all in the Factory.