欧美性猛交XXXX免费看蜜桃,成人网18免费韩国,亚洲国产成人精品区综合,欧美日韩一区二区三区高清不卡,亚洲综合一区二区精品久久

打開(kāi)APP
userphoto
未登錄

開(kāi)通VIP,暢享免費電子書(shū)等14項超值服

開(kāi)通VIP
java通過(guò)修改類(lèi)的字節碼實(shí)現aop功能
      在jdk5.0版本中,添加了一個(gè)新的接口java.lang.instrument.Instrumentation,這個(gè)接口可以用來(lái)在類(lèi)加載的時(shí)候對類(lèi)的字節碼進(jìn)行修改,改變類(lèi)的功能的實(shí)現。通過(guò)這種方法,我們就可以實(shí)現aop的功能,這是和proxy動(dòng)態(tài)代理的不同的另一種aop的實(shí)現。
     這種方法的原理很簡(jiǎn)單,就是通過(guò)修改編譯器已經(jīng)編譯好的字節碼來(lái)修改類(lèi),和我們通常修改類(lèi)源碼來(lái)實(shí)現對類(lèi)的修改差不多。只不過(guò)是在兩個(gè)不同的層次進(jìn)行的修改。
     一下是使用這個(gè)接口的具體方法。
    第一步:
    需要實(shí)現  java.lang.instrument.Instrumentation這個(gè)接口,通過(guò)在這個(gè)接口的實(shí)現類(lèi)中,在加載類(lèi)的時(shí)候修改類(lèi)的字節碼。以下是接口的實(shí)現 Transformer.java
public class Transformer implements ClassFileTransformer {
   //在程序運行之前就被jvm調用的方法
   public static void premain(String args, Instrumentation inst) {
        inst.addTransformer(new Transformer());
    }
    public byte[] transform(ClassLoader loader, String className,
            Class<?> classBeingRedefined, ProtectionDomain protectionDomain,
            byte[] classfileBuffer) throws IllegalClassFormatException {
        byte[] result =null; //定義新的字節碼存儲變量
        //在此通過(guò)修改類(lèi)的字節碼 classfileBuffer,來(lái)更改類(lèi)。
        return result; //返回新的字節碼
    }
}
第二步:
需要將
Transformer類(lèi)的class文件生成jar文件,如t.jar,在jar文件的MANIFEST.MF添加 Premain-Class: Transformer 這一項。在運行程序時(shí),需要在jvm使用如下參數 -javaagent:t.jar 。這樣jvm在運行時(shí),就會(huì )先找到Premain-Class: Transformer  這一項指定的Transformer類(lèi)的premain方法,運行此方法。也就實(shí)現了在以后的類(lèi)的加載中,對類(lèi)的字節碼進(jìn)行修改的功能。

        就是使用
java.lang.instrument.Instrumentation接口的方法。那么如何實(shí)現aop功能呢,這就需要在更改字節碼的時(shí)候,在類(lèi)的功能上添加aop方面的功能。
       現在我們看看如何實(shí)現在方法的調用前和返回時(shí)打印當前時(shí)間的aop功能。
      先更改Transformer的transform方法
public byte[] transform(ClassLoader loader, String className,
            Class<?> classBeingRedefined, ProtectionDomain protectionDomain,
            byte[] classfileBuffer) throws IllegalClassFormatException {
        byte[] result =classfileBuffer; //定義新的字節碼存儲變量
        //在此通過(guò)修改類(lèi)的字節碼 classfileBuffer,來(lái)更改類(lèi)。
        if (loader != ClassLoader.getSystemClassLoader()) {
            return classfileBuffer;
        }

        ClassReader reader = new ClassReader(classfileBuffer);
        ClassWriter writer = new ClassWriter(true);
        ClassAdapter adapter = new PerfClassAdapter(writer, className);
        reader.accept(adapter, true);
        result = writer.toByteArray();
        return result; //返回新的字節碼
    }

這樣就通過(guò)PerfClassAdapter類(lèi)來(lái)修改字節碼.
PerfClassAdapter.java
public class PerfClassAdapter extends ClassAdapter {
    private String className;
    public PerfClassAdapter(ClassVisitor visitor, String theClass) {
        super(visitor);
        this.className = theClass;
    }
    public MethodVisitor visitMethod(int arg,
            String name,
            String descriptor,
            String signature,
            String[] exceptions) {
        MethodVisitor mv = super.visitMethod(arg,
                name,
                descriptor,
                signature,
                exceptions);
        MethodAdapter ma = new PerfMethodAdapter(mv, className, name);
        return ma;
    } 
}
PerfMethodAdapter.java
public class PerfMethodAdapter extends MethodAdapter {
    private String _className, _methodName;
   
    public PerfMethodAdapter(MethodVisitor visitor,
            String className,
            String methodName) {
        super(visitor);
        _className = className;
        _methodName = methodName;
    }

    public void visitCode() {
        this.visitLdcInsn(_className);
        this.visitLdcInsn(_methodName);
        this.visitMethodInsn(INVOKESTATIC,
                "
AOP_LOG",
                "start",
                "(Ljava/lang/String;Ljava/lang/String;)V");
        super.visitCode();
    }

    public void visitInsn(int inst) {
        switch (inst) {
        case Opcodes.ARETURN:
        case Opcodes.DRETURN:
        case Opcodes.FRETURN:
        case Opcodes.IRETURN:
        case Opcodes.LRETURN:
        case Opcodes.RETURN:
        case Opcodes.ATHROW:
            this.visitLdcInsn(_className);
            this.visitLdcInsn(_methodName);
            this.visitMethodInsn(INVOKESTATIC,
                    "AOP_LOG",
                    "end",
                    "(Ljava/lang/String;Ljava/lang/String;)V");
            break;
        default:
            break;
        }
        super.visitInsn(inst);
    }
}
AOP_LOG.java
public class
AOP_LOG{
   
    public static void start(String className, String methodName) {
        System.out.println(new StringBuilder(className)
                .append(‘\t‘)
                .append(methodName)
                .append("\tstart\t")
                .append(System.currentTimeMillis()));       
    }
    public static void end(String className, String methodName) {
        System.out.println(new StringBuilder(className)
                .append(‘\t‘)
                .append(methodName)
                .append("\tend\t")
                .append(System.currentTimeMillis()));       
    }
}
這些類(lèi)結合起來(lái),就實(shí)現了在方法的調用前,會(huì )調用
AOP_LOG類(lèi)的start方法,在方法返回后,調用AOP_LOG類(lèi)的end方法。

現在寫(xiě)個(gè)測試類(lèi)來(lái)測試一下。
TSMain.java
public class TSMain {

    public static void main(String[] args) {
        TSMain tsm = new TSMain();
        tsm.printClassName();
    }
   
    public void printClassName(){
        System.out.println("hello "+this.getClass().getName());
    }
}

運行命令如下:
=>java -javaagent:t.jar  classpath cpdir TSMain  #
cpdir 需要用到的類(lèi)的路徑

輸出結果如下:
TSMain    main    start    1179374205562
TSMain    <init>    start    1179374205562
TSMain    <init>    end    1179374205562
TSMain    printClassName    start    1179374205562
hello TSMain
TSMain    printClassName    end    1179374205562
TSMain    main    end    1179374205562


到這里就完成整個(gè)aop的功能實(shí)現了。需要補充說(shuō)明的是,這里修改類(lèi)的字節碼是使用了asm的基礎類(lèi)庫,所以需要導入這些asm的jar文件。
本站僅提供存儲服務(wù),所有內容均由用戶(hù)發(fā)布,如發(fā)現有害或侵權內容,請點(diǎn)擊舉報。
打開(kāi)APP,閱讀全文并永久保存 查看更多類(lèi)似文章
猜你喜歡
類(lèi)似文章
Java 將字符串動(dòng)態(tài)生成字節碼的實(shí)現方法
spring用Aop實(shí)現計算器驗證(注解方式)
.Net平臺AOP技術(shù)研究
Android埋點(diǎn)方案的簡(jiǎn)單實(shí)現-AOP之AspectJ
Java正則引發(fā)的思考 | 淘寶網(wǎng)綜合業(yè)務(wù)平臺團隊博客
[Q&A]Ruby中如何動(dòng)態(tài)調用類(lèi)及其方法
更多類(lèi)似文章 >>
生活服務(wù)
分享 收藏 導長(cháng)圖 關(guān)注 下載文章
綁定賬號成功
后續可登錄賬號暢享VIP特權!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服

欧美性猛交XXXX免费看蜜桃,成人网18免费韩国,亚洲国产成人精品区综合,欧美日韩一区二区三区高清不卡,亚洲综合一区二区精品久久