PicoContainer is a mature dependency injector framework similar to spring-core or Guice. It presents the advantage to be quite small (~260Ko) and yet very complete.

The advantages of dependency injection are numerous

Specifically to IzPack, PicoContainer allows

How to inject dependencies

Dependencies definitions

With pico, you create and manage your own container. Once created, you can

pico = new PicoBuilder().withConstructorInjection().withCaching().build();
pico.addComponent(CliAnalyzer.class);
CliAnalyzer cliAnalyzer = pico.getComponent(CliAnalyzer.class);

Here you create a new container, add CliAnalyzer as a dependency and get the instance of CliAnalizer.
The container is configured to "cache" dependencies. Meaning, it insures that there is only one instance of this component created. It is the same as a Singleton in Guice.

Expect some particular cases, you don't need to lookup for your component using the container. Exceptions are when component are constructed dynamically like panels. In this case, we add the panel and get the instance from the compiler.

In most case, you should use injection to get dependencies.

Injection methods

Two injections methods have been used primary used.

  1. Injection by constructor.
  2. Injection by provider
Injection by constructor :

(see http://picocontainer.com/constructor-injection.html)
PicoContainer supports many types of injections but the preferred way is to pass dependencies in the constructor.

For example, given the following class :

public class AClass {
 public AClass(CliAnalyzer cliAnalyzer){
  // Use cliAnalyzer
 }
}
pico = new PicoBuilder().withConstructorInjection().withCaching().build();
pico.addComponent(CliAnalyzer.class);
pico.addComponent(AClass.class);
AClass aClass = pico.getComponent(AClass.class);

The instance of AClass will be constructed using the instance of CliAnalyzer.

Injection by provider :

(see http://picocontainer.com/providers.html)
Provider gives more flexibility to construct the component instance and it is useful to do some works prior to instantiation.

It is used to create component which need informations from xml (like AutomatedInstallData). All providers are available in packages *.container.provider

Injection of primitives :

(see http://picocontainer.com/component-configuration.html)
PicoContainer gives the possibilities to inject primitives (String, Integer, ...). They are resolved by name and it is used to inject the install file name in components.

How to add a component in IzPack

If you create a component, you can add it to the container so that it will be avaible as a dependency.

On the compiler, the container is configured by the class com.izforge.izpack.compiler.container.CompilerContainer

On the installer, there are several containers :