Introduction
Authors: Aslak Hellesoy, Jon Tirsen
Basics
This is a quick introduction to PicoContainer’s most important features. Read through it to get an idea of what PicoContainer is and isn’t.
PicoContainer’s most important feature is its ability to instantiate arbitrary objects. This is done through its API, which is similar to a hash table. You can put java.lang.Class objects in and get object instances back.
Example:
MutablePicoContainer pico = new DefaultPicoContainer();
pico.addComponent(ArrayList.class);
List list = pico.getComponent(ArrayList.class);
(i) MutablePicoContainer API
This code does the same as this:
List list = new ArrayList();
With a trivial example such as this there is no point in using PicoContainer. This was just to illustrate the basic API. PicoContainer becomes useful with larger number of classes and interfaces having complex dependencies between each other:
Complex Dependencies
Juicer Example
|
|
(Green means class, Yellow means interface). PicoContainer identifies dependencies by looking at the constructors of registered classes ( Constructor Injection ). PicoContainer can also be though of as a generic factory that can be configured dynamically. PicoContainer is able to instantiate a complex graph of several interdependent objects.
Write some simple classes and interfaces with dependencies
The “Juicer Example” diagram above could translate to the following code (we added a concrete Peelable):
public interface Peelable {
void peel();
}
public class Apple implements Peelable {
public void peel() { }
}
public class Peeler implements Startable {
private final Peelable peelable;
public Peeler(Peelable peelable) {
this.peelable = peelable;
}
public void start() {
peelable.peel();
}
public void stop() { }
}
public class Juicer {
private final Peelable peelable;
private final Peeler peeler;
public Juicer(Peelable peelable, Peeler peeler) {
this.peelable = peelable;
this.peeler = peeler;
}
}
(Note that this code suffers from the anti-pattern Propagating Dependency but let’s not worry about that for now )
Assemble components
You tell PicoContainer what classes to manage by registering them like this (the order of registration has no significance):
MutablePicoContainer pico = new DefaultPicoContainer();
pico.addComponent(Apple.class);
pico.addComponent(Juicer.class);
pico.addComponent(Peeler.class);
(i) MutablePicoContainer API
Instantiate components
You can tell PicoContainer to give you an instance of a class like this (provided it has been registered previously):
Juicer juicer = (Juicer) pico.getComponent(Juicer.class);
This will cause PicoContainer to do something similar to this behind the scenes (except that PicoContainer uses reflection):
Peelable peelable = new Apple();
Peeler peeler = new Peeler(peelable);
Juicer juicer = new Juicer(peelable, peeler);
return juicer;
Note how PicoContainer figures out that Apple is a Peelable, so that it can be passed to Peeler and Juicer’s constructors.
Container hierarchies
PicoContainer provides a powerful alternative to the Singleton . With container hierarchies you can create singleton-like objects where you have fine grained control over the visibility scope of the instance. (The singleton pattern is static and global – it won’t allow more than one instance, and it is visible from anywhere. Not nice when you try to build a large enterprise application from it).
A container (and its registered components) can get access to components registered in a parent container, but not vice-versa. Consider this example, using the classes from above:
THIS WON’T WORK! It is for illustration purposes only!
// Create x hierarchy of containers
MutablePicoContainer x = new DefaultPicoContainer();
MutablePicoContainer y = new DefaultPicoContainer( x );
MutablePicoContainer z = new DefaultPicoContainer( y );
// Assemble components
x.addComponent(Apple.class);
y.addComponent(Juicer.class);
z.addComponent(Peeler.class);
// Instantiate components
Peeler peeler = (Peeler) z.getComponent(Peeler.class); // WON'T WORK! peeler will be null
peeler = (Peeler) x.getComponent(Peeler.class); // WON'T WORK! This will throw an exception
Juicer juicer = (Juicer) y.getComponent(Juicer.class);
This can be visualised as follows:
Let’s analyse what will happen here:
- Line 12 will work fine. z will be able to resolve the dependencies for Peeler (which is Fruit) from the parent container.
- Line 14 will return null, as x can’t see Peeler.
- Line 16 will throw an exception, since Juicer’s dependency to Peeler can’t be satisfied (z can’t be seen by y).
Since this obviously won’t work, keep in mind that this was just an exercise to illustrate how container hierarchies work. For a more concrete example of the usage of container hierarchies, see PicoContainer Web .
Lifecycle
PicoContainer has support for Lifecycle . If your classes implement Startable , you can control the lifecycle of all your objects with a simple method call on the container. The container will figure out the correct order of invocation of start()/stop() all the objects managed by the container.
Calling start() on the container will call start() 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:
MutablePicoContainer.start()
MutablePicoContainer.stop()!
|
|
Lifecycle also works for hierarchies of containers. 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. The pictures below show what happens when start() and stop() are called on a container with children.
MutablePicoContainer.start()
MutablePicoContainer.stop()
|
|
In order for 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.
Example
MutablePicoContainer parent = new DefaultPicoContainer(new Caching());
MutablePicoContainer child = new DefaultPicoContainer(parent); // We must let the parent container know about the child container.
parent.addComponent(child); // This will start the parent, which will start the child.
parent.start();
Lifecycle is really only going to work for PicoContainers that are also caching component instances. Caching was a default in PicoContainer 1.x, but is not for 2.x – be warned!
Calling lifecycle methods on a container that has a parent container will not propagate the lifecycle to the parent container.
Read more about lifecycle here .
Contrasting Usage Styles
With PicoContainer you add components and get instances out in two styles.
Classic bean style:
pico = new DefaultPicoContainer();
pico.addComponent(ComponentOneImpl.class) // by type
pico.addComponent(ComponentTwoImpl.class) // by type
pico.addComponent(new ComponentThreeImpl()) // by instance
pico.addComponent(ComponentFourImpl.class) // by type
ComponentFourImpl four = pico.getComponent(ComponentFourImpl.class);
Or you can use a fluent style if you want:
ComponentFour four = new DefaultPicoContainer().addComponent(ComponentOne.class)
.addComponent(ComponentTwo.class).addComponent(new ComponentThree())
.addComponent(ComponentFour.class).getComponent(ComponentFour.class);
分享到:
相关推荐
spring的ioc容器详细讲解,理解springioc容器
Spring IoC加载流程讲解以及IoC思想和依赖倒置原则
一篇关于从java技术层面介绍容器注入的文档,值得推荐!
Spring讲解PPT,了解Spring的起源历史,Ioc、AOP等知识。
详细讲解ioc控制反转机制,供大家深入了解ioc机制
IOC详解IOC详解IOC详解IOC详解IOC详解IOC详解IOC详解IOC详解
在自己博客里自己动手实现IOC和MVC系列中的全部源码 http://blog.csdn.net/ajun_studio/article/details/6831241
spring.doc spring.doc spring.docspring.doc spring.doc spring.doc spring.doc spring.doc
Ioc,使用容器按需要创建对象,避免了在对象中new 对象的高耦合...........
通过项目实例详细讲解spring的IOC和AOP思想,通俗易懂的项目demo
IoC对象实例IoC对象实例IoC对象实例
IOC模式 c#经典例子 IOC 例子 IOC模式 c#经典例子 IOC 例子 IOC模式 c#经典例子 IOC 例子
详细讲解了springioc的各种注入方式以及对应的java方式。讲解了springioc和DI的区别,以及注入特殊复杂的属性
spring ioc指的是控制反转,IOC容器负责实例化、定位、配置应用程序中的对象及建立这些对象间的依赖。交由Spring容器统一进行管理,从而实现松耦合
spring Ioc容器配置 IOC容器数据源配置 <!-- 配置数据源 --> destroy-method="close"> <value>org.gjt.mm.mysql.Driver <value>jdbc:mysql://localhost:3306/demo <value>root ...
我们从一个简单的容器开始,一步步的重构,最后实现一个基本的Spring框架的雏形,为了帮助我们更加深入的理解Spring的IoC的原理和源码。 详细内容见博文: 【SSH进阶之路】一步步重构容器实现Spring的IoC——从一个...
spring ioc.jar springioc必备开发工具包
SpringIoc示例代码,SpringIoc示例代码,SpringIoc示例代码,SpringIoc示例代码
主要为大家详细解析了Spring中IoC优点与缺点,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
Spring通过注解实现IOC,Spring通过注解实现IOC,Spring通过注解实现IOC