Magnolia 6.0 reached end of life on June 26, 2019. This branch is no longer supported, see End-of-life policy.
Magnolia uses dependency injection. This means that object dependencies are injected automatically at the time the object is instantiated. The benefit of injecting dependencies in this way is that you can change the implementation of the object which is depended on without having to change the way dependencies are retrieved. A further benefit is testability.
This type of dependency is different from module dependencies. It is a code/object level dependency that defines the relationship between objects, not a dependency between modules.
The term dependency injection (DI) is often used together with inversion of control (IoC). IoC is the principle and DI is the implementation. The concepts are related but at Magnolia we talk only about DI. To learn how IoC was implemented at Magnolia, see Concept IoC in Magnolia.
Components in Magnolia are defined in the module descriptor. Modules can define components of the same type. A definition in a module takes precedence over definitions in modules that it depends on. This allows modules to override and customize components in other modules.
For example, suppose you want to implement a MailSender
component. If another Magnolia module already implements such a component, you can override it by declaring a module dependency on the module that provides the original MailSender
component and by making sure that your component definition uses the same type.
The module descriptor can specify components for different containers. This is done using the id
element. You will rarely use a container other than main
.
This example module descriptor defines a component of type GeoService
which is an interface. The actual implementation is GeoServiceImpl
.
<!DOCTYPE module SYSTEM "module.dtd"> <module> <name>my-module</name> <version>1.0</version> <components> <id>main</id> <!-- Container ID --> <component> <type>com.acme.geo.GeoService</type> <implementation>com.acme.geo.GeoServiceImpl</implementation> </component> </components> </module>
To retrieve a component, declare a dependency on it. Here is an example declaring a dependency on a component that needs to be injected (GeoService
). The example uses the constructor injection type. Field and setter injection are also supported.
public class SomeGeoAwareModel extends RenderingModelImpl { private final GeoService geoService; @Inject public SomeGeoAwareModel(GeoService geoService) { this.geoService = geoService; } public String execute() { } }