Dependency injection and inversion of control

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.

Defining object components

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>

Injecting component dependencies

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() {
  }
}
<component>
  <type>com.acme.geo.GeoService</type>
  <implementation>com.acme.geo.GeoServiceImpl</implementation>
</component>
Feedback

DX Core

×

Location

This widget lets you know where you are on the docs site.

You are currently perusing through the DX Core docs.

Main doc sections

DX Core Headless PaaS Legacy Cloud Incubator modules