Java字节码实现Aop

以下代码需要asm-5.0.2.jar和asm-commons-5.0.2.jar两个包。

package com.shihuan.asm.account;

public class Account {
	
	public void operation() {
		System.out.println("shihuan operation...");
	}
	
}


package com.shihuan.asm.account;

public class SecurityChecker {

	public static void checkSecurity() {
		System.out.println("SecurityChecker.checkSecurity...");
	}
	
}


package com.shihuan.asm.account;

public class TestAccount {

	public static void main(String[] args) {
		Account a = new Account();
		a.operation();
	}

}


package com.shihuan.asm.account;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;

import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;

public class AccountAsm {

	public static void main(String[] args) throws IOException {
		ClassReader cr = new ClassReader("com.shihuan.asm.account.Account");
		ClassWriter cw = new ClassWriter(cr, ClassWriter.COMPUTE_MAXS);
		ClassVisitor cv = new ClassVisitor(Opcodes.ASM5, cw){
			
			public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
				
				MethodVisitor mv = cv.visitMethod(access, name, desc, signature, exceptions);  // 先得到原始的方法
				MethodVisitor newMethod = mv;
				
				if (mv != null) {
					if ("operation".equals(name)){ // 此处的operation即为需要修改的方法 ,修改方法內容
						// 访问需要修改的方法
						newMethod = new MethodVisitor(Opcodes.ASM5, mv) {
							
							public void visitCode() {
								visitMethodInsn(Opcodes.INVOKESTATIC, "com/shihuan/asm/account/SecurityChecker","checkSecurity", "()V", false);
								super.visitCode();
							}
							
						};
						
						
					}
				}
				
				return newMethod;
			}
			
			
			
		};
		cr.accept(cv, ClassReader.SKIP_DEBUG);
		
		byte[] code = cw.toByteArray();
		
		OutputStream fos = new FileOutputStream("D:/myworkspace/JavaAsm/bin/com/shihuan/asm/account/Account.class");
		fos.write(code);
		fos.close();
	}

}


----------------------------------------------------------------------------------
上面的代码是笔者测试Asm用的,下面笔者做一个抓取Oracle驱动包中原生态SQL语句的例子。
需要在工程中添加ojdbc6.jar文件。

package oracle.jdbc.driver;

public class OracleMyEnd {

	public static void getMySqlInfo(OraclePreparedStatement opsObj) {
		System.out.println("ShiHuan Is Sql --->> " + opsObj.sqlObject.originalSql);
	}
	
}


package oracle.jdbc.driver;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;

import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;

public class OracleAsm {

	public static void main(String[] args) {
		try {
			ClassReader cr = new ClassReader("oracle.jdbc.driver.OraclePreparedStatement");
			ClassWriter cw = new ClassWriter(cr, ClassWriter.COMPUTE_MAXS);
			ClassVisitor cv = new ClassVisitor(Opcodes.ASM5, cw){
				
				public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
					
					MethodVisitor mv = super.visitMethod(access, name, desc, signature, exceptions);  // 先得到原始的方法
					MethodVisitor newMethod = mv;
					
					if (mv != null) {
						if ("executeInternal".equals(name)){ // 此处的executeInternal即为需要修改的方法 ,修改方法內容
							// 访问需要修改的方法
							newMethod = new MethodVisitor(Opcodes.ASM5, newMethod) {								
								public void visitCode() {
									visitVarInsn(Opcodes.ALOAD, 0);
									visitMethodInsn(Opcodes.INVOKESTATIC, "oracle/jdbc/driver/OracleMyEnd","getMySqlInfo", "(Loracle/jdbc/driver/OraclePreparedStatement;)V", false);
									super.visitCode();
								}
								
							};
						}
					}
					
					return newMethod;
				}
				
			};
			
			cr.accept(cv, ClassReader.SKIP_DEBUG);
			
			byte[] code = cw.toByteArray();
			
			OutputStream fos = new FileOutputStream("D:/myworkspace/JavaAsm/bin/oracle/jdbc/driver/OraclePreparedStatement.class");
			fos.write(code);
			fos.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

}

猜你喜欢

转载自shihuan830619.iteye.com/blog/2070863