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 moduleSYSTEM"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>Copy
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.