webwork的IOC(基于2.1.X版本)
webwork的ioc其实在webwork中使用起来挺方便的,虽然其功能不算强大,但是已经能很好的满足我们一般的需要了,就算我们使用spring 的ioc,如果不使用特别的功能,其一般我们也是基于接口,然后有个set方法,通过set来注入,没有太多的区别,不同的是webwork的ioc需要依赖xwork,而spring却是依赖spring这个容器。
webwork的ioc是怎么进行注入的了,我们从代码中进行分析:
首先看看拦截器的代码:
public class ComponentInterceptor extends AroundInterceptor {
//~ Static fields/initializers /////////////////////////////////////////////
public static final String COMPONENT_MANAGER = "com.opensymphony.xwork.interceptor.component.ComponentManager";
//~ Methods ////////////////////////////////////////////////////////////////
protected void after(ActionInvocation dispatcher, String result) throws Exception {
}
protected void before(ActionInvocation dispatcher) throws Exception {
ComponentManager container = (ComponentManager) ActionContext.getContext().get(COMPONENT_MANAGER);
if (container != null) {
container.initializeObject(dispatcher.getAction());
}
}
}
主要的代码用黑体标注出来了,container实际就是组件管理器,这里是一个ComponentManager接口的实现 DefaultComponentManager,然后调用了该类的方法initializeObject(dispatcher.getAction ());而dispatcher.getAction()实际就是所调用的action对象,我们再来看看 DefaultComponentManager做了什么。
public void initializeObject(Object obj) {
loadResource(obj, obj.getClass(), this);
}
private Class loadResource(Object resource, Class clazz, DefaultComponentManager dcm) {
// ~由此来判断是否要进行依赖注入
boolean resourceNotLoaded = !dcm.loadOrder.contains(resource);
if (resourceNotLoaded) {
Map resources = getResourceDependencies(clazz);
for (Iterator iterator = resources.entrySet().iterator();
iterator.hasNext();) {
Map.Entry mapEntry = (Map.Entry) iterator.next();
Class depResource = (Class) mapEntry.getKey();
DefaultComponentManager newDcm = (DefaultComponentManager) mapEntry.getValue();
try {
ResourceEnablerPair pair = setupAndOptionallyCreateResource(newDcm, depResource);
setupResource(resource, pair.enabler, pair.resource);
} catch (Exception e) {
e.printStackTrace();
if (log.isDebugEnabled()) {
log.debug("Error loading or setting up resource: " + resources.getClass().getName(), e);
}
}
}
dcm.alreadyLoaded.add(clazz);
if (resource instanceof Initializable) {
Initializable initializable = (Initializable) resource;
initializable.init();
}
dcm.resourceInstances.put(clazz, resource);
dcm.loadOrder.add(resource);
}
// now return this class's enabler
Class enabler = (Class) dcm.enablers2.get(clazz);
return enabler;
}
private Map getResourceDependencies(Class resourceClass) {
List interfaces = new ArrayList();
//~ 将所有的interface放入interfaces链表中
addAllInterfaces(resourceClass, interfaces);
Map dependencies = new HashMap();
for (Iterator iterator = interfaces.iterator(); iterator.hasNext();) {
Class anInterface = (Class) iterator.next();
DefaultComponentManager dcm = this;
while (dcm != null) {
Class possibleResource = (Class) dcm.enablers.get(anInterface);
if (possibleResource != null) {
dependencies.put(possibleResource, dcm);
break;
}
dcm = dcm.fallback;
}
}
return dependencies;
}
private void addAllInterfaces(Class clazz, List allInterfaces) {
if (clazz == null) {
return;
}
Class[] interfaces = clazz.getInterfaces();
allInterfaces.addAll(Arrays.asList(interfaces));
addAllInterfaces(clazz.getSuperclass(), allInterfaces);
}
重要的代码都用黑体进行了标注,方法initializeObject中所调用的loadResource(obj, obj.getClass(), this);就执行了查找接口,并注入接口实现类整个过程。
loadResource首先调用了getResourceDependencies(clazz);而getResourceDependencies又调用了addAllInterfaces(resourceClass, interfaces);addAllInterfaces作用就是取得这个类包括这个类的父类的所有实现的接口,而getResourceDependencies方法就是对这个接口进行过滤,返回只是在配置中有的接口。setupAndOptionallyCreateResource(newDcm, depResource);进行的就是创建这些接口的实现类的对象,这个代码的内容如下:
private ResourceEnablerPair setupAndOptionallyCreateResource(DefaultComponentManager newDcm, Class depResource) throws Exception {
ResourceEnablerPair pair = new ResourceEnablerPair();
Object newResource = newDcm.resourceInstances.get(depResource);
if (newResource == null) {
newResource = ObjectFactory.getObjectFactory().buildBean(depResource);
}
pair.resource = newResource;
Class enabler = loadResource(newResource, depResource, newDcm);
pair.enabler = enabler;
return pair;
}
因为准备创建出来的接口实现类对象的接口可能又实现了其他的接口,因此再调用了loadResource(newResource, depResource, newDcm)。对象创建了,然后就是注入这个对象,setupResource(resource, pair.enabler, pair.resource)就是起这个作用的。代码如下:
private void setupResource(Object resource, Class enabler, Object newResource) {
if (enabler == null) {
return;
}
try {
enabler.getMethods()[0].invoke(resource, new Object[] {newResource});
} catch (Exception e) {
e.printStackTrace();
if (log.isDebugEnabled()) {
log.debug("Error invoking method for resource: " + resource.getClass().getName(), e);
}
}
}
每个接口只有一个set方法,通过反射机制调用这个方法将创建出来的接口实现对象注入进去。整个IOC就完成了。
posted on 2007-03-22 10:30
小小~咖啡豆 阅读(328)
评论(0) 编辑 收藏 所属分类:
WebWork