User Documentation

One minute description
Two minute tutorial
Five minute introduction
Advanced Topics
FAQ
Container
Components
Terminology
Mock Objects
Inversion of Control Types

Patterns

Inversion of Control 
Dependency Injection 
Constructor Injection 
Setter Injection 
Interface Implementation Separation 
Lifecycle 
Antipatterns

Developer Documentation

 Current build status
How To Contribute
Relative Volunteering
Release Process

Project Information

Slogan
Mailing lists
Source Repositories
Open Issues
Blog entries 
Statistics
Team
Sister Projects
TShirts

Miscellaneous

Differentiators
Nirvana

Full Sitemap

Feeds


Site
News
Implementation hiding and Hot swapping

Authors: Aslak Hellesoy

Basics

Circular dependencies and transparent hot swapping is supported by ImplementationHidingComponentAdapter. In order to achieve this, your components must honour Interface Implementation Separation. It is then done simply by instantiating the container with a CachingComponentAdapterFactory around a ImplementationHidingComponentAdapterFactory.

Note: The ImplementationHidingComponentAdapter was removed from PicoContainer and is now located in the component NanoProxytoys.

Example

Consider two classes, Wife and Husband:

public class Wife implements Woman {
    public final Man man;

    public Wife(Man man) {
        this.man = man;
    }

    public Man getMan() {
        return man;
    }
}
public class Husband implements Man {
    public final Woman woman;

    public Husband(Woman woman) {
        this.woman = woman;
    }

    public int getEndurance() {
        return 10;
    }
}
public interface Woman {
    Man getMan();
}


public interface Man {
    int getEndurance();
}

We can register them both in PicoContainer, and thanks to ImplementationHidingComponentAdapter's lazy materialisation, we can have mutual dependencies:

ComponentAdapterFactory caf = new CachingComponentAdapterFactory(new ImplementationHidingComponentAdapterFactory());
DefaultPicoContainer pico = new DefaultPicoContainer(caf);
// Register two classes with mutual dependencies on each other. (See ImplementationHidingComponentAdapterFactoryTestCase)
pico.registerComponentImplementation(Wife.class);
pico.registerComponentImplementation(Husband.class);

Woman woman = (Woman) pico.getComponentInstance(Wife.class);
assertEquals(10, woman.getMan().getEndurance());

Note that we have to cast to the interface they implement, since what the container gives us back is actually dynamic proxies that forward to the real subjects (that are hidden from you). Here is a UML object diagram that describes the relationships between the objects in the system.

When a component is requested via getComponentInstance(), only a dynamic proxy for the real subject is created. Nothing more. This means that after line 7 is executed, the only object that exists is the proxy for Woman. The hidden delegates aren't instantiated until a method is called on the proxy. (The delegates are lazily instantiated).

After line 8 is executed, all 4 objects will exist. The call to getMan() will cause the real Wife subject to be instantiated. This will in turn instantiate the Man proxy to satisfy Wife's constructor. Finally, the call to getEndurance() will instantiate the Husband subject.

In addition to supporting mutual dependencies, ImplementationHidingComponentAdapterFactory also lets you hotswap the delegates. This can be done by casting the component instance to Swappable and pass in the new subject via the hotswap() method. (All proxy objects created by ImplementationHidingComponentAdapter implement Swappable).

// let the woman use another man
Man superman = new Superman();
((Swappable)woman.getMan()).hotswap(superman);

assertEquals(1000, woman.getMan().getEndurance());


public class Superman implements Man {
    public int getEndurance() {
        return 1000;
    }
}

This will swap out the Man proxy's current delegate with a new one. Completely transparently to the Wife object. When the wife now calls a methods on her Man, it will be delegated to a new instance. Scary?