快速业务通道

基于Eclipse RCP简化IoC实现 - 编程入门网

作者 佚名技术 来源 NET编程 浏览 发布时间 2012-06-21
(3) 时间:2011-01-05 天极 朱先忠

四.ASM和java.lang.instrument代理

前一节所描述的各种注入策略通常都依靠存在一个容器来提供一个空的入口点-应用程序用来请求正确配置的对象。然而,在开发我们的IoC插件时,我们想维护一种透明的方法-这主要基于下面两个理由:

RCP采用复杂的类加载器和实例化策略来保持插件独立性和强制实施可见性约束。我们并不想修改或替换这样的策略来引入我们的基于容器的初始化规则。

显式地引用这样一个入口点(在我们例子中,是指定义在Service Locator插件中的service()方法)将强迫应用程序开发者采用一种显式的模式和逻辑来检索初始化的组件。这意味着,在应用程序代码中存在某种库锁定。因此,我们要定义一个并不需要一种显式的引用它的codebase的协作性插件。

由于这些原因,我们将引入在java.lang.instrument包中定义的java转换代理(在J2SE 5.0及更高版本中才可用)。其实,一个转换代理就是一个对象,它实现了定义一个唯一的transform()方法的java.lang.instrument.ClassFileTransformer接口。当一个转换实例被注册到JVM时,对于每一个在JVM中创建的类都将调用该转换器实例。在JVM加载这个类之前,该转换器能够存取类的字节码并能够修改该类的描述。

转换代理能够被使用命令行参数(形式为"-javaagent:jarpath[=options]")注册到JVM。其中,jarpath是指向包含该代理类的JAR文件的路径,而options是该代理的一个参数串。这个代理JAR文件使用一个特定的manifest属性来指定实际的代理类,这要求必须定义一个方法"public static void premain(String options,Instrumentation inst)"。这个代理premain()方法是在应用程序的main()方法执行之前被调用的,而且它能够使用传入的java.lang.instrument.Instrumentation类实例注册一个实际的转换器。

在我们的例子中,我们定义一个代码-它实现字节码操作以透明地把运行时刻调用添加到我们的IoC容器(Service Locator插件)。该代理将通过核实存在于类中的Serviceable注解来识别可服务的对象。然后,它修改所有可用的构造器-把回调添加到IoC容器-以便它能够在实例化时刻配置和初始化该对象。

让我们假定这个对象依赖于外部服务:

@Serviceable public class ServiceableObject {   public ServiceableObject() {    System.out.println("Initializing...");   }   @Injected public void aServicingMethod(    Service s1,    AnotherService s2) {     // ...省略...    }   }

在代理修改完之后,它的字节码将会与通过正常编译这个类得到的字节码一致:

@Serviceable public class ServiceableObject {   public ServiceableObject() {    ServiceLocator.service(this);    System.out.println("Initializing...");   }   @Injected public void aServicingMethod(    Service s1,    AnotherService s2) {     // ...省略...    } }

使用这种方案,现在我们能够正确地配置可服务的对象并且使之用于应用程序中而不需要开发者"硬性地绑定"对于容器的依赖性。开发者将只需要使用可服务的注解来标志可服务的对象即可。代理代码如下所示:

public class IOCTransformer implements ClassFileTransformer {   public byte[] transform(ClassLoader loader,String className,Class<?> classBeingRedefined, ProtectionDomain protectionDomain,byte[] classfileBuffer)    throws IllegalClassFormatException {     System.out.println("Loading " + className);     ClassReader creader = new ClassReader(classfileBuffer);     //分析类文件

凌众科技专业提供服务器租用、服务器托管、企业邮局、虚拟主机等服务,公司网站:http://www.lingzhong.cn 为了给广大客户了解更多的技术信息,本技术文章收集来源于网络,凌众科技尊重文章作者的版权,如果有涉及你的版权有必要删除你的文章,请和我们联系。以上信息与文章正文是不可分割的一部分,如果您要转载本文章,请保留以上信息,谢谢!

分享到: 更多

Copyright ©1999-2011 厦门凌众科技有限公司 厦门优通互联科技开发有限公司 All rights reserved

地址(ADD):厦门软件园二期望海路63号701E(东南融通旁) 邮编(ZIP):361008

电话:0592-5908028 传真:0592-5908039 咨询信箱:web@lingzhong.cn 咨询OICQ:173723134

《中华人民共和国增值电信业务经营许可证》闽B2-20100024  ICP备案:闽ICP备05037997号