JavaBeans属性)。这是一种由PicoContainer专用的独特的方法。另外,它也用于HiveMind和Spring中。
我们将采纳类型2的一种变体-通过注解的方法提供服务。一种声明一个依赖性的方法可以如下实现:
@Injected public void aServicingMethod(
Service s1,AnotherService s2) {
//把s1和s2保存到类变量中
//以便在需要时使用它们
}
控制反转容器将查找注入的注解并且调用要求的参数来调用该方法。为了把IoC加入到Eclipse平台中,我们把在服务和可服务的对象之间进行绑定的代码打包为一个Eclipse插件。该插件定义一个扩展点(名为com.onjava.servicelocator.servicefactory)-它可以用来为应用程序提供服务工厂。无论何时当一个可服务的对象需要配置时,该插件将请求到一个工厂的服务实例。ServiceLocator类负责实现所有这些工作,正如下面的代码片断所描述的(我们跳过处理分析扩展点的代码-因为这些代码非常直接):
/**
*把要求的依赖性注入到参数对象中。它扫描可服务的对象-通过查找标识有{@link Injected}注解的方法。参数类型是从匹配的方法中提取的。每一种类型的实例是从注册的工厂中创建的(见{@link IServiceFactory})。相应于所有参数类型的实例都被创建完毕,该方法被调用,并继续检查下一个方法。
*
* @param-要被服务的可服务对象
* @抛出ServiceException异常
*/
public static void service(Object serviceable)
throws ServiceException {
ServiceLocator sl = getInstance();
if (sl.isAlreadyServiced(serviceable)) {
//避免多次初始化问题-由于存在构造器分层
System.out.println("Object " +serviceable + " has already been configured ");
return;
}
System.out.println("Configuring " + serviceable);
//为请求的服务分析类
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<?> klass :m.getParameterTypes()){
IServiceFactory factory = sl.getFactory(klass,ann.optional());
if (factory == null) {
skip = true;
break;
}
Object service = factory.getServiceInstance();
//检查:确保返回的服务的类是从该方法中盼望的那一个
assert(service.getClass().equals(klass) || klass.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实现 |