`
barryzhong
  • 浏览: 21260 次
  • 性别: Icon_minigender_1
社区版块
存档分类

Java编程的动态特性,使用BCEL代码生成工具,极大简化Class Transformation开发

阅读更多
 
       在写过《Java编程的动态特性,从Reflection到Runtime Class Transformation》入门日记之后,笔者继续在此方向上实践了2天的日夜煎熬,最终实现了最初的想法。然而在临末之时忽然发现一条捷径,倘若早采用这条捷径,将会少走很多弯路,便可以更快的完成最初的目标。所以本篇入门日记主要介绍这条捷径,以便各位搞技术的兄弟姐妹待用之时便可以少走很多弯路且节省很多时间。
     为了让没做过类似工作的读者能同笔者一样身临其境,故在介绍
该捷径之后简要的说明一下笔者的设计初衷以及,不感兴趣的直接跳过。
假设有实体类ServiceOrder,它有一个方法allocateResource,笔者期望在运行时拦截这个allocateResource方法调用。样例类如下:

@LifecycleMeta(ServiceableLifecycleMeta.class)
@Entity 

public class ServiceOrder {

    @Transition(Schedule.class)
    public void allocateResource(){
        //...
    }


第一步设计运行时拦截这个方法的实现,如下: 

@LifecycleMeta(ServiceableLifecycleMeta.class)

@Entity
public
 class ServiceOrder {
     @Transition(Schedule.class)
     public void allocateResource() {
             final InterceptController controller = new InterceptController();
             final InterceptContext context = new InterceptContext(this, "allocateResource", new Class[]{});
             controller.exec(context, new java.util.concurrent.Callable<java.lang.Void>() {
                 allocateResource$Impl();
                 return null;
             }
     }

      @Transition(Schedule.class)
      public void allocateResource$Impl() {
         // original logic
      }


第二步,设计好可编译的目标代码样式后,编译出class文件。
第三步,然后通过BCEL提供的一个工具类(捷径)BCELifier来生成Java代码,这个代码就是如何生成目标class文件的代码,如下:
图片
后面是生成到System.out的代码片段

图片

第四步,根据一些变化来改写这个代码。前提是需要有一点字节码,本地变量表,操作数栈等得基本知识,就如上一篇日记中提到的那些入门基础和路线,这些内容都比较容易理解。
比如优化减少指令,比如通过ldc直接加载当前的class,而不需要通过this.getClass()来获得。
比如拦截的方法可以接受参数,可以接受基本数据类型的参数或者引用类型参数或者数组。
比如方法的返回值处理等等。
第五步,测试一下生成的代码,可以通过写test drive来运行它,或者通过Byte Code Visualizer以及Class File Editor来查看生成的方法的指令序列和Class ConstantPool中的常量。迭代第四步和第五步,就可以完成主要字节码转换的主要工作了。
笔者做的工作是一个指令一个指令自己写上去的,走了很多弯路,比如在处理如何在字节码层面如何引用基本数据类型的Class对象,匿名内置类和outer class之间的各种Class属性设置等等,而这些在生成的代码中都有确切的指令,如上面图片中18行左右的createFieldAccess部分。笔者从来没有使用过java.lang.Long.TYPE这个静态常量,原来这就是基础数据类型long对应的Class对象,其他的基本数据类型同上。
 
 设计初衷
如果对设计不感兴趣,可以直接跳过后面的片段。
     笔者初衷是要实现方法拦截。众所周知实现方法拦截可以有不少办法,比如如果是在非框架下工作,那么工程师自己可以采用动态代理的方式;或者可以采用代理的设计模式;或者用一些“高级”AOP的工具;在框架下工作可以采用标准组件框架下提供的组件,比如在EJB环境下工作,对于EJB业务方法的拦截可以采用JavaEE的Interceptor,但是如果相对非组件类方法进行拦截,标准化组件框架并不提供类似的功能。在上面介绍的这么多方法拦截实现手段中,出了现有的AOP工具外(修改字节码的实现方式),大都有一些额外的开销。一般需要Java反射加动态代理,且需要在设计的架构中单独增加一层来实现。若不采用Java反射和动态代理,则需要增加一层非常具体的接口层。如果这些接口层本身就是架构设计者需要的部分,那么无可厚非;倘若是为了封装和隐藏框架的行为而特意设计的这样的接口层,就显得有些笨重了,程序员在编写代码的时候总会显得不自然。最臭名昭著的就是早期的EJB1.x和EJB2.x,应用程序员为了编写业务逻辑必须额外实现框架强制要求的接口,而且还要编写标准的部署描述符文件以及容器指定的部署描述符文件才能运行自己的程序。总而言之,为了在框架中实现方法拦截(包括声称为应用提供很多服务,如安全性服务,事务服务,消息服务,邮件服务等等)而产生额外的编码需求,这是不受欢迎的。作者的初衷就是在要提供额外服务的前提下,避免增加额外的编码工作,使这些服务的运行犹如春雨般,润物细无声。
在介绍完笔者的初衷后,我们更进一步看看细节。对于web或者企业应用开发者来说,一直以来大家都在争论“充血型”模型和“贫血型”模型的优劣,只有开始,没有结束。我们不在这里谈论这个没有结论的话题,倒是可以引用Martin Fowler的一句话以及一个大原则。M大师说,“尽管面向对象编程语言已经占领了编程语言的市场,然而主宰编程思想的依旧是面向过程”。颇有讽刺的意味啊!大家都在用牛刀杀鸡。另外在做架构设计时总会碰到一些纠结的问题,就比如“贫血型”和“充血型”(别担心我们不会谈论这个),人们总是纠结于到底要在业务层或者实体层暴漏什么给其他的层次。M大师一言以蔽之,要多思考隐藏(封装)什么,而不是暴漏什么。M大师提到通常他自己要隐藏的不仅仅是实现,而更多的是设计。关于M大师我们就说到这里。笔者喜欢面向对象的封装,倾向于“充血型”模型。旨在实体层次中封装(隐藏)业务对象的生命周期管理。就像RESTful充分利用HTTP协议一样,笔者要充分利用JPA框架中的各种工具。

分享到:
评论

相关推荐

    java字节码例子 可以动态修改类 bcel

    在Java中,我们可以使用字节码技术来实现动态代码修改、增强或优化,这在很多场景下非常有用,比如AOP(面向切面编程)、性能监控和调试工具等。 BCEL(Byte Code Engineering Library),全称Java字节码操纵库,是...

    BCEL类代码解析工具

    BCEL代码解析工具 ,执行java -jar BCELCode.jar -d file.txt 即可解密。

    JAVA字节码操作库 BCEL.7z

    总的来说,BCEL是一个强大的工具,它为Java开发者提供了一种直接操作字节码的途径,极大地扩展了Java编程的可能性。无论是进行代码分析、动态生成还是其他高级功能,BCEL都是一个值得信赖的伙伴。

    JAVA字节码操作库 BCEL

    2. **字节码生成**:BCEL提供了一套接口和类,使得开发者可以动态地生成字节码,这对于创建动态代理、AOP(面向切面编程)等场景非常有用。 3. **代码优化**:通过修改字节码,BCEL可以实现代码的优化,例如去除...

    修改javaclass工具包

    在Java开发过程中,有时我们可能面临这样的情况:手中只有已编译的`.class`文件而没有对应的`.java`源代码。在这种情况下,如果需要对已有的`.class`文件进行修改,传统的通过修改源代码并重新编译的方式就行不通了...

    java源码:JAVA字节码操作库 BCEL.zip

    总的来说,BCEL是一个用于Java字节码操作的重要工具,对于那些需要在运行时动态生成或修改Java类的开发者来说,它是一个不可或缺的资源。通过深入学习和使用BCEL,你可以实现一些高级的编程技巧,如代码混淆、性能...

    基于Java的字节码操作库 BCEL.zip

    BCEL在许多领域都有应用,如动态代码生成、程序分析、性能监控以及安全控制等。 BCEL的核心功能主要包括以下几个方面: 1. **类分析与解析**:BCEL能够读取Java .class文件,并将其转换为内部表示形式,即`Class...

    commons-bcel,阿帕奇公地BCEL.zip

    这个库允许开发者分析、创建、修改和编译Java类文件,为开发动态类生成和代码分析工具提供了强大的基础。下面我们将深入探讨这个库的核心功能、应用场景以及使用方法。 1. **核心功能**: - **类文件分析**:BCEL...

    java 动态编译打包 动态编译可以用于实现动态代码生成、动态加载、插件化等功能

    Java 动态编译打包是Java开发中的一个重要技术,它允许程序在运行时生成和编译源代码,然后即时加载到应用程序中。这种技术在许多场景下都非常有用,例如实现动态代码生成、动态加载和插件化系统。下面将详细讨论...

    Java反编译工具,将class文件反编译成Java文件

    Java反编译是编程领域中一个重要的技术环节,它允许开发者查看和理解已经编译成字节码(.class文件)的Java程序的原始源代码。这种能力在多种情况下非常有用,例如,当我们需要分析开源软件的实现细节,或者当我们...

    基于java的字节码操作库 BCEL.zip

    1. **代码生成与动态代理**:BCEL可以用于在运行时生成新的类或者方法,这对于创建动态代理、AOP(面向切面编程)框架等有极大的帮助。例如,你可以使用BCEL来动态地构建一个实现了特定接口的类,并在其中插入自定义...

    bcel-5.2 动态修改CLASS文件

    可以动态修改CLASS文件,但是修改后的CLASS文件无法反编译,是一个郁闷的事情,但是这个咚咚还是很好用 提供的只是jar包,没有demo,下载的朋友请注意了!! 只是为了提供jar包下载的方便

    ant-apache-bcel-1.6.4.jar.zip

    总结,Ant Apache BCEL 1.6.4作为Java字节码操作的重要工具,为开发者提供了强大的字节码生成和分析能力,极大地扩展了Java开发的可能性。理解并熟练运用BCEL,可以在许多复杂场景下提升开发效率和软件质量。

    bcel-6.5.0-src.zip

    在Java开发领域,理解字节码对于优化程序性能、实现动态代码生成以及进行安全控制等方面具有重要意义。BCEL(Byte Code Engineering Library)是Apache软件基金会的一个开源项目,它提供了一组API来操作和分析Java...

    JAVA源码JAVA字节码操作库BCEL

    JAVA源码JAVA字节码操作库BCEL

    java资源JAVA字节码操作库BCEL

    java资源JAVA字节码操作库 BCEL提取方式是百度网盘分享地址

    四种动态生成Java代码的方法.rar

    Java代码动态生成是一种在运行时根据特定需求创建和执行代码的技术。这在处理复杂逻辑、元编程、插件系统或优化性能时非常有用。本文将详细介绍四种常见的Java代码动态生成方法,并探讨它们的优缺点以及性能表现。 ...

    bcel-6.0 bcel-6.0

    这个工具主要用于生成和操作Java虚拟机(JVM)字节码,常用于编译器、动态代理、代码分析和优化等场景。 **标签“bcel”** 标签“bcel”进一步明确了我们讨论的主题,即BCML库。BCML是开源软件,由Apache软件基金...

Global site tag (gtag.js) - Google Analytics