zoukankan      html  css  js  c++  java
  • java 动态AOP

    一、實現機制:

    在运行期,所有类加载器加载字节码前,前进行拦截。並將代碼植入。可以对所有类进行织入。

    二、實現方式:

    1. 實現ClassFileTransformer 接口

    2. 添加以下方法(必須):

    public static void premain(String options, Instrumentation ins) {   
    //注册我自己的字节码转换器
    ins.addTransformer(new MyClassFileTransformer());
    }

    實例:

     1 package com.aop;
    2
    3 import java.io.IOException;
    4 import java.lang.instrument.ClassFileTransformer;
    5 import java.lang.instrument.IllegalClassFormatException;
    6 import java.lang.instrument.Instrumentation;
    7 import java.security.ProtectionDomain;
    8
    9 import javassist.CannotCompileException;
    10 import javassist.ClassPool;
    11 import javassist.CtClass;
    12 import javassist.CtMethod;
    13 import javassist.NotFoundException;
    14
    15 public class AopTransformer implements ClassFileTransformer {
    16
    17 /**
    18 * 字节码加载到虚拟机前会进入这个方法
    19 */
    20 @Override
    21 public byte[] transform(ClassLoader loader, String className,
    22 Class<?> classBeingRedefined, ProtectionDomain protectionDomain,
    23 byte[] classfileBuffer) throws IllegalClassFormatException {
    24
    25 // javassist的包名是用点分割的,需要转换下
    26 if (className.indexOf("/") != -1) {
    27 className = className.replaceAll("/", ".");
    28 }
    29
    30 try {
    31 // 通过包名获取类文件
    32 CtClass cc = ClassPool.getDefault().get(className);
    33
    34 // 获得指定方法名的方法
    35 CtMethod m = cc.getDeclaredMethod("sayhello");
    36
    37 // 在方法执行前插入代码
    38 m.insertBefore("{System.out.println(\"在HelloTest.sayhello之前執行\");}");
    39 m.insertAfter("{System.out.println(\"在HelloTest.sayhello之後執行\");}");
    40 m = cc.getDeclaredMethod("sayGoodBye");
    41
    42 // 在方法执行前插入代码
    43 m.setBody("{System.out.println(\"修改HelloTest.sayGoodBye的方法體\");}");
    44 return cc.toBytecode();
    45 } catch (NotFoundException e) {
    46 } catch (CannotCompileException e) {
    47 e.printStackTrace();
    48 } catch (IOException e) {
    49 // 忽略异常处理
    50 }
    51 return null;
    52 }
    53
    54 /**
    55 * 在main函数执行前,执行的函数
    56 *
    57 * @param options
    58 * @param ins
    59 */
    60 public static void premain(String options, Instrumentation ins) {
    61 // 注册我自己的字节码转换器
    62 ins.addTransformer(new AopTransformer());
    63 }
    64 }
     1 package com.test;
    2
    3 public class HelloTest {
    4 public void sayhello() {
    5 System.out.println("HelloTest sayhello");
    6 }
    7 public void sayGoodBye() {
    8 System.out.println("HelloTest sayGoodBye");
    9 }
    10
    11 public static void main(String[] args) {
    12 HelloTest ht = new HelloTest();
    13 ht.sayhello();
    14 ht.sayGoodBye();
    15 }
    16 }


    三、執行

    1. 需要告诉JVM在启动main函数之前,需要先执行premain函数。首先需要将premain函数所在的类打成jar包。并修改该jar包里的META-INF\MANIFEST.MF 文件,MANIFEST.MF 文件內容如下:

    1 Manifest-Version: 1.0
    2 Premain-Class: com.aop.AopTransformer
    3 Can-Redefine-Classes: true
    4 Can-Retransform-Classes: true
    5 Can-Set-Native-Method-Prefix: true

    2. 將aop.jar放到同一目錄

    3. 使用java命令執行main方法:

    java -javaagent:.\aop.jar HelloTest

    4. 執行結果比較

    如果沒有添加aop執行結果如下:

    HelloTest sayhello
    HelloTest sayGoodBye

    添加aop執行結果如下:

    在HelloTest.sayhello之前執行
    HelloTest sayhello
    在HelloTest.sayhello之後執行
    修改HelloTest.sayGoodBye的方法體






     

  • 相关阅读:
    ANR----以及如何定位是前端问题还是后台问题?
    一个App或者web端,你怎么展开测试
    创业性公司,你以什么方式来进行对真机的成本降低 ?
    判断查找IP的两种方法
    接口测试(四)总结及小技巧笔记
    接口测试 (三)功能分类及配置文件引入
    接口测试(二) 优化项目分层及cookies值带入
    接口测试模块完整版
    接口测试入门
    unittest框架(惨不忍睹低配版)
  • 原文地址:https://www.cnblogs.com/liubin0509/p/2373797.html
Copyright © 2011-2022 走看看