Java动态编程——Javassist

动态编程是相对于静态编程而言的,平时咱们讨论比较多的就是静态编程语言,例如Java,与动态编程语言,例如JavaScript。
html

在静态编程中,类型检查是在编译时完成的,而动态编程中类型检查是在运行时完成的。所谓动态编程就是绕过编译过程在运行时进行操做的技术,在Java中有以下几种方式:java


~~~~反射:就是经过在运行时得到类型信息而后作相应的操做。编程


~~~~动态编译:动态编译是从Java 6开始支持的,主要是经过一个JavaCompiler接口来完成的。经过这种方式咱们能够直接编译一个已经存在的java文件,也能够在内存中动态生成Java代码,动态编译执行。服务器


~~~~调用JavaScript引擎:Java 6加入了对Script(JSR223)的支持。这是一个脚本框架,提供了让脚本语言来访问Java内部的方法。你能够在运行的时候找到脚本引擎,而后调用这个引擎去执行脚本。这个脚本API容许你为脚本语言提供Java支持。框架


~~~~动态生成字节码:这种技术经过操做Java字节码的方式在JVM中生成新类或者对已经加载的类动态添加元素。编程语言


动态编程解决什么问题ide

在静态语言中引入动态特性,主要是为了解决一些使用场景的问题。工具

彻底使用静态编程也办的到,只是付出的代价比较高,没有动态编程来的优雅。例如依赖注入框架Spring使用了反射,而Dagger2 却使用了代码生成的方式(APT)。this

如 编码

一、在那些依赖关系须要动态确认的场景: 

二、须要在运行时动态插入代码的场景,好比动态代理的实现。 

三、经过配置文件来实现相关功能的场景


Javassist

操做java字节码的工具BECL/ASM/CGLIB/Javassit

其中有两个比较流行,一个是ASM,一个是Javassit。


ASM 直接操做字节码指令,执行效率高,要是使用者掌握Java类字节码文件格式及指令,对使用者的要求比较高。

Javassit 提供了更高级的API,执行效率相对较差,但无需掌握字节码指令的知识,对使用者要求较低。

Javassit 是一个开源的分析、编辑和建立Java字节码的类库。是由东京工业大学的数学和计算机科学系的 Shigeru Chiba (千叶 滋)所建立的。它已加入了开放源代码JBoss应用服务器项目,经过使用Javassist对字节码操做为JBoss实现动态AOP框架。javassist是jboss的一个子项目,其主要的优势,在于简单,并且快速。直接使用java编码的形式,而不须要了解虚拟机指令,就能动态改变类的结构,或者动态生成类。


Javassist中最为重要的是ClassPool,CtClass ,CtMethod 以及 CtField这几个类。


ClassPool:一个基于HashMap实现的CtClass对象容器,其中键是类名称,值是表示该类的CtClass对象。默认的ClassPool使用与底层JVM相同的类路径,所以在某些状况下,可能须要向ClassPool添加类路径或类字节。


CtClass:表示一个类,这些CtClass对象能够从ClassPool得到。


CtMethods:表示类中的方法。


CtFields :表示类中的字段。


例子:

建立Class,Field,Method,Constructor

    public static void main(String[] args) throws Exception {
        ClassPool pool = ClassPool.getDefault();
        CtClass person = pool.makeClass("com.temp.bytecodeop.Person");
        
        //建立属性
        CtField name = CtField.make("private String name;", person);
        CtField age = CtField.make("private int age;", person);
        person.addField(name);
        person.addField(age);
        
        //建立方法
        CtMethod getName = CtMethod.make("public String getName(){return name;}", person);
        CtMethod setName = CtMethod.make("public void setName(String name){this.name=name;}", person);
        person.addMethod(getName);
        person.addMethod(setName);
        
        //建立构造器        
        CtConstructor constructor = new CtConstructor(new CtClass[]{pool.get("java.lang.String"),CtClass.intType},person);
        constructor.setBody("{this.name=name; this.age=age;}");
        person.addConstructor(constructor);
        
        person.writeFile("c:/Person");
        System.out.println("success");
    }




参考文献:https://blog.csdn.net/ShuSheng0007/article/details/81269295

https://www.cnblogs.com/sunfie/p/5154246.html

相关文章
相关标签/搜索