# method-tracer **Repository Path**: binaryFox/method-tracer ## Basic Information - **Project Name**: method-tracer - **Description**: AOP的一种实现,只要给定一个入口类,几乎把该类下面的所有方法及其方法的返回的类都能监控到. 其中操作比较有意思: 1. 动态字节码生成无参构造函数的类,骗过CGLIB检测 2. 自写类加载器加载类 3. 重写CGLIB代理类,不用通过构造函数,通过实体直接生成代理类 - **Primary Language**: Java - **License**: Apache-2.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 2 - **Forks**: 0 - **Created**: 2020-12-24 - **Last Updated**: 2021-09-28 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # method-tracer #### 介绍 想写一个数据库连接工具[Kettle]连接Redis的功能,所以要知道它调用了Driver的哪些类。但是苦于很少有代码侵入性低但是能监控所有执行方法返回值的.干脆自己撸一个. 代码比较少,但是解决了几个比较头疼的问题终于算是实现了。 只要给定一个入口类,几乎把该类下面的所有方法及其方法的返回的类都能监控到. 其中操作比较有意思: 1. 动态字节码生成无参构造函数的类,骗过CGLIB检测 2. 自写类加载器加载类 3. 重写CGLIB代理类,不用通过构造函数,通过实体直接生成代理类 #### 软件说明 1. 只要一个入口类被代理,入口下面的所有类都能被代理。 2. 在入口类的方法返回值上也加了代理。 3. 原生的CGLIB是不支持通过实体生成代理的,Enhancer方法的Crate函数是需要构造方法的,但是这个项目支持。 4. [重写了Enhancer方法](https://gitee.com/binaryFox/method-tracer/blob/master/src/main/java/wang/hex/TracerEnhancer.java)(无参构造函数的类,骗过CGLIB检测),重写类加载器,使用unsafe直接跳过构造函数(如果执行构造函数Java会报错的)。 5. [实现了简单的filter机制](https://gitee.com/binaryFox/method-tracer/blob/master/src/main/java/wang/hex/TracerMethodVisitor.java) #### 使用教程 1. 测试包下 [TestDriver.class](https://gitee.com/binaryFox/method-tracer/blob/master/src/test/java/wang/hex/TestDriver.class) 有代码示意 执行效果如下 Driver下所有Connect PrepareStatement ResultSet 的方法都打印出来了 但是我们只对Driver加了代理 ``` 2020-12-24 15:48:53.644 DriverX - toString [[]] [wang.hex.DriverX@4bbfb90a] [0 ms] [e: ] 2020-12-24 15:48:53.708 DriverX - connect [[jdbc:hx2:tcp://localhost:8977/./test, {user=sa, password=sa}]] [conn1: url=jdbc:h2:tcp://localhost:8977/./test user=SA] [34 ms] [e: ] 2020-12-24 15:48:53.723 JdbcConnection - prepareStatement [[CREATE TABLE IF NOT EXISTS X1(ID INT)]] [prep2: CREATE TABLE IF NOT EXISTS X1(ID INT)] [1 ms] [e: ] 2020-12-24 15:48:53.741 JdbcPreparedStatement - execute [[]] [false] [0 ms] [e: ] 2020-12-24 15:48:53.741 JdbcPreparedStatement - close [[]] [] [0 ms] [e: ] 2020-12-24 15:48:53.742 JdbcConnection - prepareStatement [[INSERT INTO X1 VALUES (?)]] [prep3: INSERT INTO X1 VALUES (?)] [0 ms] [e: ] 2020-12-24 15:48:53.742 JdbcPreparedStatement - setInt [[1, 0]] [] [0 ms] [e: ] 2020-12-24 15:48:53.743 JdbcPreparedStatement - execute [[]] [false] [0 ms] [e: ] 2020-12-24 15:48:53.743 JdbcPreparedStatement - setInt [[1, 1]] [] [0 ms] [e: ] 2020-12-24 15:48:53.743 JdbcPreparedStatement - execute [[]] [false] [0 ms] [e: ] 2020-12-24 15:48:53.744 JdbcPreparedStatement - setInt [[1, 2]] [] [0 ms] [e: ] 2020-12-24 15:48:53.744 JdbcPreparedStatement - execute [[]] [false] [0 ms] [e: ] 2020-12-24 15:48:53.744 JdbcPreparedStatement - close [[]] [] [0 ms] [e: ] 2020-12-24 15:48:53.748 JdbcConnection - prepareStatement [[SELECT * FROM X1]] [prep4: SELECT * FROM X1] [4 ms] [e: ] 2020-12-24 15:48:53.752 JdbcPreparedStatement - executeQuery [[]] [rs7: columns: 1 rows: 6 pos: -1] [4 ms] [e: ] 2020-12-24 15:48:53.773 JdbcResultSet - next [[]] [true] [1 ms] [e: ] 2020-12-24 15:48:53.774 JdbcResultSet - getInt [[1]] [0] [0 ms] [e: ] 0 2020-12-24 15:48:53.774 JdbcResultSet - next [[]] [true] [0 ms] [e: ] 2020-12-24 15:48:53.774 JdbcResultSet - getInt [[1]] [1] [0 ms] [e: ] 1 2020-12-24 15:48:53.774 JdbcResultSet - next [[]] [true] [0 ms] [e: ] 2020-12-24 15:48:53.774 JdbcResultSet - getInt [[1]] [2] [0 ms] [e: ] 2 2020-12-24 15:48:53.774 JdbcResultSet - next [[]] [true] [0 ms] [e: ] 2020-12-24 15:48:53.774 JdbcResultSet - getInt [[1]] [0] [0 ms] [e: ] 0 2020-12-24 15:48:53.775 JdbcResultSet - next [[]] [true] [0 ms] [e: ] 2020-12-24 15:48:53.775 JdbcResultSet - getInt [[1]] [1] [0 ms] [e: ] 1 2020-12-24 15:48:53.775 JdbcResultSet - next [[]] [true] [0 ms] [e: ] 2020-12-24 15:48:53.775 JdbcResultSet - getInt [[1]] [2] [0 ms] [e: ] 2 2020-12-24 15:48:53.775 JdbcResultSet - next [[]] [false] [0 ms] [e: ] 2020-12-24 15:48:53.775 JdbcPreparedStatement - close [[]] [] [0 ms] [e: ] ```