former(new IOCTransformer());
}
}
ConstructorVisitor、ClassAnnotationVisitor、 ClassWriter以及ClassConstructorWriter使用ObjectWeb ASM库执行字节码操作。
在Eclipse RCP中实现反转控制(IoC)(4)
时间:2011-03-14
ASM使用visitor模式以事件流的方式处理类数据(包括指令序列)。当解码一个已有的类时, ASM为我们生成一个事件流,调用我们的方法来处理这些事件。当生成一个新类时,过程相反:我们生成一个事件流,ASM库将其转换成一个类。注意,这里描述的方法不依赖于特定的字节码库(这里我们使用的是ASM);其它的解决方法,例如BCEL或Javassist也是这样工作的。
我们不再深入研究ASM的内部结构。知道ConstructorVisitor和 ClassAnnotationVisitor对象用于查找标记为Serviceable类,并收集它们的构造函数已经足够了。他们的源代码如下:
public class ClassAnnotationVisitor extends ClassAdapter {
private boolean matches = false;
public ClassAnnotationVisitor(ClassVisitor cv) {
super(cv);
}
@Override
public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
if (visible && desc.equals("Lcom/onjava/servicelocator/annot/Serviceable;")) {
matches = true;
}
return super.visitAnnotation(desc, visible);
}
@Override
public MethodVisitor visitMethod(int access, String name, String desc,
String signature, String[] exceptions) {
if (matches)
return super.visitMethod(access, name, desc, signature, exceptions);
else {
return null;
}
}
}
public class ConstructorVisitor extends EmptyVisitor {
private Set<Method> constructors;
public ConstructorVisitor() {
constructors = new HashSet<Method>();
}
public Set<Method> getConstructors() {
return constructors;
}
@Override
public MethodVisitor visitMethod(int access, String name, String desc,
String signature, String[] exceptions) {
Type t = Type.getReturnType(desc);
if (name.indexOf("<init>") != -1 && t.equals(Type.VOID_TYPE)) {
constructors.add(new Method(name, desc));
}
return super.visitMethod(access, name, desc, signature, exceptions);
}
}
一个ClassConstructorWriter的实例将修改收集的每个构造函数,注入对Service Locator插件的调用:
com.onjava.servicelocator.ServiceLocator.service(this); ASM需要下面的指令以完成工作:
// mv is an ASM method visitor,
// a class which allows method manipulation
mv.visitVarInsn(ALOAD, 0);
mv.visitMethodInsn(
INVOKESTATIC,
"com/onjava/servicelocator/ServiceLocator",
"service",
"(Ljava/lang/Object;)V");
第一个指令将this对象引用加载到栈,第二指令将使用它。它二个指令调用ServiceLocator的静态方法。
现在我们具有了构建应用程序的所有元素。我们的例子可用于显示用户感兴趣的名言警句。它由四个插件组成:
Service Locator插件,提供IoC框架
FortuneService插件,提供服务管理fortune cookie
FortuneInterface插件,发布访问服务所需的公共接口
FortuneClient插件,提供Eclipse应用程序,以Eclipse视图中显示名言警句。
在Eclipse RCP中实现反转控制(IoC)(5)
时间:2011-03-14
采用IoC设计,使服务的实现与客户分离;服务实例可以修改,对客户没有影响。图2显示了插件间的依赖关系。
图2. 插件间的依赖关系: ServiceLocator和接口定义使服务和客户分离。
如前面所述,Se |