300 likes | 324 Views
PicoContainer. Presented by: Jim O’Hara Ed Kausmeyer Jingming Zhang. Lightweight Containers. Attempts to build alternatives to the mainstream J2EE technologies A common obstacle: How to wire together different elements
E N D
PicoContainer Presented by: Jim O’Hara Ed Kausmeyer Jingming Zhang
Lightweight Containers • Attempts to build alternatives to the mainstream J2EE technologies • A common obstacle: • How to wire together different elements • How do you fit together this web controller architecture with that database interface backing when they were built by different teams with little knowledge of each other? • Lightweight Containers • Frameworks that have taken a stab at this problem and are branching out to provide a general capability to assemble components from different layers • PicoContainer, Spring
Overview of PicoContainer • Lightweight and highly embeddable container for components that honor Dependency Injection • Small, simple container for arbitrary components/services • Originally implemented in Java • Now available for other platforms and languages also (including C# and Ruby) • http://opensource.thoughtworks.com/projects/picocontainer.jsp
Overview of PicoContainer • Not a replacement for a J2EE container • Does not offer any infrastructure services out of the box • Can use the monitor support of PicoContainer to react on internal events e.g. by logging
Benefits of PicoContainer • Embeddable inside other applications • 50k jar that has no external dependencies except JDK 1.3 • Compact in size • Non-intrusive • Components don't have to implement any funny APIs and can be POJOs • Very extensible design: Enables virtually any form of extensions to the core
Benefits of PicoContainer • Modularize how dependencies between parts of an application are laced up • Common to have dependencies scattered all over • Can be valuable for large projects • Improve how components are configured in an application • Improve the testability of code
Dependency Injection • A way of instantiating components and lacing them together with other dependent components • Main idea: Have a separate object, an assembler, that populates a field in a class to be created with an appropriate implementation for an interface that class needs, resulting in a dependency • That is, a component user specifies the interfaces it needs, and the implementations of the required components are provided at creation time • Decouple the caller of the component from the implementation
Types of Dependency Injection • Constructor Dependency Injection (CDI): an object gets all its dependencies via the constructor • Setter Dependency Injection (SDI): the container or embedder hands dependencies to a component via setter methods after instantiation
Dependency Injection In PicoContainer • PicoContainer supports CDI and SDI • PicoContainer identifies dependencies by looking at the constructors of registered classes (CDI) • PicoContainer can be thought of as a generic factory that can be configured dynamically • PicoContainer is able to instantiate a complex graph of several interdependent objects
Components In PicoContainer • Components are implemented as ordinary Java classes and do not typically have to rely on any PicoContainer APIs • The components are assembled in a container using a simple Java API that is similar to an intelligent hash map utilizing the type of its values • This allows PicoContainer to instantiate arbitrary objects • You can put java.lang.Class objects in and get object instances back
Components In PicoContainer • A component user specifies the interfaces it needs, and PicoContainer provides the implementations of the required components at creation time • This is what Dependency Injection is all about • A component can be used in the PicoContainer without importing or extending any interfaces or defined in the PicoContainer assembly
Demonstration: Juicer Example • Example taken from http://www.picocontainer.org/Five+minute+introduction
Container Hierarchies • Containers provide a powerful alternative to the singleton antipattern • The singleton pattern is static and global; it won't allow more than one instance and is visible from anywhere • Containers serve as singleton-like objects that provide fine-grained control over the visibility scope of the instance
Container Hierarchies • A container (and its registered components) can get access to components registered in a parent container, but not vice-versa
//Container Hierarchy Example // Create x hierarchy of containers MutablePicoContainer x = new DefaultPicoContainer(); MutablePicoContainer y = new DefaultPicoContainer(x); MutablePicoContainer z = new DefaultPicoContainer(x); // Assemble components x.registerComponentImplementation(Apple.class); y.registerComponentImplementation(Juicer.class); z.registerComponentImplementation(Peeler.class);
//Container Hierarchy Example Continued // Instantiate components Peeler peeler = (Peeler)z.getComponentInstance(Peeler.class); // WON'T WORK! peeler will be null peeler = (Peeler) x.getComponentInstance(Peeler.class); // WON'T WORK! This will throw an exception Juicer juicer = (Juicer)y.getComponentInstance(Juicer.class); • First line will work fine; z will be able to resolve the dependencies for Peeler (which is Apple) from the parent container • Second line will return null, as x can't see Peeler • Third line will throw an exception, since Juicer's dependency to Peeler can't be satisfied (z can't be seen by y)
Lifecycle • One third of Inversion of Control • Inversion of Control = dependency resolution + configuration + lifecycle • Concerns the post composition life of a component • Most commonly encountered lifecycle concepts: start, stop, dispose
Lifecycle • The lifecycle of components are easy to manage in PicoContainer • Lifecycle callbacks are supported by implementing the lifecycle interfaces • PicoContainer provides two simple interfaces for lifecycle: Startable and Disposable • A lifecycle can be extended or totally customized
Lifecycle • If a set of classes implement Startable, the lifecycle of all the objects can be controlled with method calls on the container • The container will figure out the correct order of invocation of start() or stop() for all the objects it manages
Lifecycle • Calling start() on the container will call stop() on all container-managed objects in the order of their instantiation • This means starting with the ones that have no dependencies, and ending with the ones that have dependencies on others
Lifecycle • Calling start() on a container with child containers will start all the containers in a breadth-first order, starting with itself • Likewise, calling stop() will call stop() on all containers in the hierarchy in a depth-first order
Lifecycle • In order for a hierarchy-aware lifecycle to work, child containers must be registered as components in their parent container • Just creating a container with another one as a parent will not cause the parent container to know about the child container • Calling lifecycle methods on a child container will not propagate the lifecycle to its parent container
Lifecycle Example: A Direct Approach MutablePicoContainer parent = new DefaultPicoContainer(); MutablePicoContainer child = new DefaultPicoContainer(parent); // We must let the parent container know // about the child container. parent.registerComponentInstance(child); // This will start the parent, which // will start the child. parent.start();
Lifecycle Example: An Indirect Approach MutablePicoContainer parent = new DefaultPicoContainer(); parent.registerComponentImplementation("child", DefaultPicoContainer); // This will instantiate the child container // passing the parent (itself) as parent // container. // No need to register the child in the parent // here. MutablePicoContainer child = (MutablePicoContainer) parent.getComponentInstance("child"); // This will start the parent, which will start // the child. parent.start();
NanoContainer, for expanding capabilities • Builds on top of PicoContainer the support for several scripting metalanguages (XML, Groovy, Bsh, Javascript and Jython), AOP, Web frameworks (Struts and WebWork), SOAP, JMX, and much more
import org.picocontainer.*; • import org.picocontainer.defaults.*; • public class DITest{ • public static void main(String[] args){ • //Two ways to test Inversion of Control in pico container • //Both use Dependency Injection Patten. • //Constructor Injection with PicoContainer indirectly • System.out.println("Constructor Injection indirectly:"); • MyMovieFinder mmf = new MyMovieFinder(); • mmf.testWithPico(); • //Constructor Injection with PicoContainer directly • System.out.println("constructor Injection directly:"); • MutablePicoContainer pico = new DefaultPicoContainer(); • pico.registerComponentImplementation(MovieFinderImpl.class); • pico.registerComponentImplementation(MovieLister.class); • MovieLister lister = (MovieLister) pico.getComponentInstance(MovieLister.class); • lister.listFinder(); • //Constructing Object without using PicoContainer • System.out.println("Construct Object without PicoContainer:"); • //String title = "Once Upon a Time in the West"; • MovieFinder finder = new MovieFinderImpl(); • lister = new MovieLister(finder); • lister.listFinder(); • System.exit(0); • } • }
Output of Executing DITest Class F:\SE510>java DITest Constructor Injection indirectly: MovieFinder was listed by MovieLister@1cfb549 constructor Injection directly: MovieFinder was listed by MovieLister@186d4c1 Construct Object without PicoContainer: MovieFinder was listed by MovieLister@f9f9d8
References • Page with several links for information about PicoContainerhttp://www.picocontainer.org/ • One-minute description: provides an overview of PicoContainer and lists some of its benefitshttp://www.picocontainer.org/One+minute+description • Two minute tutorial: provides code snippets that serve as a introduction to PicoContainerhttp://www.picocontainer.org/Two+minute+tutorial • Five minute introduction: provides code snippets that serve as a introduction to PicoContainer and explains the concepts of container hierarchies and lifecyclehttp://www.picocontainer.org/Five+minute+introduction • Paper: Inversion of Control Containers and the Dependency Injection patternhttp://www.martinfowler.com/articles/injection.html • Constructor Dependency Injection with PicoContainer, a post-J2EE Nirvana: Explains Inversion of Control (IoC) and Constructor Dependency Injection (CDI) in PicoContainer and NanoContainerhttp://conferences.oreillynet.com/cs/os2004/view/e_sess/5294