PicoContainer的工作流程
PicoContainer的工作流程
1、注册组件
客户端代码:
MutablePicoContainer pico = new DefaultPicoContainer();
pico.registerComponentImplementation(Boy.class);
通过下面方法注册组件:
public ComponentAdapter registerComponentImplementation(Object componentKey, Class componentImplementation, Parameter[] parameters){
ComponentAdapter componentAdapter = componentAdapterFactory.createComponentAdapter(componentKey, componentImplementation, parameters);
registerComponent(componentAdapter);
return componentAdapter;
}
我们先来看看registerComponent:
public ComponentAdapter registerComponent(ComponentAdapter componentAdapter) {
Object componentKey = componentAdapter.getComponentKey();
if (componentKeyToAdapterCache.containsKey(componentKey)) {
throw new DuplicateComponentKeyRegistrationException(componentKey);
}
componentAdapters.add(componentAdapter);
componentKeyToAdapterCache.put(componentKey, componentAdapter);
return componentAdapter;
}
此方法用来注册注册组件,但是又不是直接把组件注册进去,而是通过ComponentAdapter进行了一次包装,也就是说,在ComponentAdapter中应该对组件有一些另外的描述。
现在再来看ComponentAdapter。
ComponentAdapter由其工厂componentAdapterFactory产生,而componentAdapterFactory其实是DefaultComponentAdapterFactory的实例。
public class DefaultComponentAdapterFactory implements ComponentAdapterFactory, Serializable {
public ComponentAdapter createComponentAdapter(Object componentKey, Class componentImplementation, Parameter[] parameters){
return new CachingComponentAdapter(new ConstructorInjectionComponentAdapter(componentKey, componentImplementation, parameters));
}
}
这样,我们就得到了一个CachingComponentAdapter的ComponentAdapter。但是,这个CachingComponentAdapter也不是最内部的那个ComponentAdapter。CachingComponentAdapter继承了DecoratingComponentAdapter,而DecoratingComponentAdapter使用了Decorate模式,其目的是为目标对象添加功能。CachingComponentAdapter类重写了DecoratingComponentAdapte的getComponentInstance方法,实现了缓存的功能:
public Object getComponentInstance(PicoContainer container){
if (instanceReference.get() == null) {
instanceReference.set(super.getComponentInstance(container));
}
return instanceReference.get();
}
由此可以看出,注册一个组件是注册了它的ComponentAdapter,而默认情况下,其实是最终注册了ConstructorInjectionComponentAdapter。
2、获取组件实例
客户端代码:
Girl girl = (Girl) pico.getComponentInstance(Girl.class);
girl.kissSomeone();
先来看getComponentInstance:
public Object getComponentInstanceOfType(Class componentType) {
final ComponentAdapter componentAdapter = getComponentAdapterOfType(componentType);
return componentAdapter == null ? null : getInstance(componentAdapter);
}
工作交给了getInstance:
private Object getInstance(ComponentAdapter componentAdapter) {
// ...
Object instance = componentAdapter.getComponentInstance(this);
// ...
return instance;
// ...
}
有了上面的经验,这次就不罗嗦了,直捣黄龙,直接看ConstructorInjectionComponentAdapter的getComponentInstance方法:
public Object getComponentInstance(PicoContainer container){
// ...
final Constructor constructor;
constructor = getGreediestSatisfiableConstructor(guardedContainer);
Object[] parameters = getConstructorArguments(guardedContainer, constructor);
return newInstance(constructor, parameters);
// ...
}
这里就可以很明显的看出来了:先找到最合适(即可以使用最多参数)的构造子,然后设置其参数,最后生成一个实例返回给客户端。