用
}
在Eclipse RCP中实现反转控制(IoC)(2)
时间:2011-03-14
反转控制容器将查找Injected注释,使用请求的参数调用该方法。我们想将IoC引入Eclipse平台,服务和可服务对象将打包放入Eclipse插件中。插件定义一个扩展点 (名称为com.onjava.servicelocator.servicefactory),它可以向程序提供服务工厂。当可服务对象需要配置时,插件向一个工厂请求一个服务实例。ServiceLocator类将完成所有的工作,下面的代码描述该类(我们省略了分析扩展点的部分,因为它比较直观):
/**
* Injects the requested dependencies into the parameter object. It scans
* the serviceable object looking for methods tagged with the
* {@link Injected} annotation.Parameter types are extracted from the
* matching method. An instance of each type is created from the registered
* factories (see {@link IServiceFactory}). When instances for all the
* parameter types have been created the method is invoked and the next one
* is examined.
*
* @param serviceable
* the object to be serviced
* @throws ServiceException
*/
public static void service(Object serviceable) throws ServiceException {
ServiceLocator sl = getInstance();
if (sl.isAlreadyServiced(serviceable)) {
// prevent multiple initializations due to
// constructor hierarchies
System.out.println("Object " + serviceable
+ " has already been configured ");
return;
}
System.out.println("Configuring " + serviceable);
// Parse the class for the requested services
for (Method m : serviceable.getClass().getMethods()) {
boolean skip = false;
Injected ann = m.getAnnotation(Injected.class);
if (ann != null) {
Object[] services = new Object[m.getParameterTypes().length];
int i = 0;
for (Class<?> class : m.getParameterTypes()) {
IServiceFactory factory = sl.getFactory(class, ann
.optional());
if (factory == null) {
skip = true;
break;
}
Object service = factory.getServiceInstance();
// sanity check: verify that the returned
// service''s class is the expected one
// from the method
assert (service.getClass().equals(class) || class
.isAssignableFrom(service.getClass()));
services[i++] = service;
}
try {
if (!skip)
m.invoke(serviceable, services);
} catch (IllegalAccessException iae) {
if (!ann.optional())
throw new ServiceException(
"Unable to initialize services on "
+ serviceable + ": " + iae.getMessage(), iae);
} catch (InvocationTargetException ite) {
if (!ann.optional())
throw new ServiceException(
"Unable to initialize services on "
+ serviceable + ": " + ite.getMessage(), ite);
}
}
}
sl.setAsServiced(serviceable);
}
在Eclipse RCP中实现反转控制(IoC)(3)
时间:2011-03-14
由于服务工厂返回的服务可能也是可服务对象,这种策略允许定义服务的层次结构(然而目前不支持循环依赖)。
前节所述的各种注入策略通常依靠容器提供一个入口点,应用程序使用入口点请求已正确配置的对象。然而,我们希望当开发IoC插件时采用一种透明的方式,原因有二:
RCP采用了复杂的类加载器和实例化策略(想一下createExecutableExtension()) 来维护插件的隔离和强制可见性限制 |