Javassist 学习笔记1

Javassist是一个开源的分析、编辑和创建Java字节码的类库。

Javassist是一个开源的分析、编辑和创建Java 字节码的类库。是由东京工业大学的数学和计算机科学系的 Shigeru Chiba (千叶 滋)所创建的。它已加入了开放源代码JBoss 应用服务器项目,通过使用Javassist对字节码操作为JBoss实现动态AOP框架。
关于java字节码的处理,目前有很多工具,如bcel, asm。不过这些都需要直接跟 虚拟机指令打交道。如果你不想了解虚拟机指令,可以采用javassist。javassist是 jboss的一个子项目,其主要的优点,在于简单,而且快速。直接使用java编码的形式,而不需要了解虚拟机指令,就能动态改变类的结构,或者动态生成类。


转自:http://yonglin4605.iteye.com/blog/1396494

我们需要创建的目标类,如下:

	public class JavassistClass{
		private String name="default";
		public JavassistClass(){
			name="me";
		}
	        public String getName() {
			return name;
		}
		public void setName(String name) {
			this.name = name;
		}
		public void execute(){
			System.out.println(name);
			System.out.println("execute ok");
		}
	}

如下为用javassist来创建类的代码:

import java.lang.reflect.Method;
import java.lang.reflect.Modifier;

import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtConstructor;
import javassist.CtField;
import javassist.CtField.Initializer;
import javassist.CtMethod;
import javassist.CtNewMethod;

public class JavassistLearn{
	
	
	public static void main(String[] args) throws Exception{
		ClassPool cp=ClassPool.getDefault();
		CtClass ctClass=cp.makeClass("com.slovef.JavassistClass");
		
		StringBuffer body=null;
		//参数  1:属性类型  2:属性名称  3:所属类CtClass
		CtField ctField=new CtField(cp.get("java.lang.String"), "name", ctClass);
		ctField.setModifiers(Modifier.PRIVATE);
		//设置name属性的get set方法
		ctClass.addMethod(CtNewMethod.setter("setName", ctField));
		ctClass.addMethod(CtNewMethod.getter("getName", ctField));
		ctClass.addField(ctField, Initializer.constant("default"));
		
		//参数  1:参数类型   2:所属类CtClass
		CtConstructor ctConstructor=new CtConstructor(new CtClass[]{}, ctClass);
		body=new StringBuffer();
		body.append("{\n name=\"me\";\n}");
		ctConstructor.setBody(body.toString());
		ctClass.addConstructor(ctConstructor);
		
		//参数:  1:返回类型  2:方法名称  3:传入参数类型  4:所属类CtClass
		CtMethod ctMethod=new CtMethod(CtClass.voidType,"execute",new CtClass[]{},ctClass);
		ctMethod.setModifiers(Modifier.PUBLIC);
		body=new StringBuffer();
		body.append("{\n System.out.println(name);");
		body.append("\n System.out.println(\"execute ok\");");
		body.append("\n return ;");
		body.append("\n}");
		ctMethod.setBody(body.toString());
		ctClass.addMethod(ctMethod);
		Class<?> c=ctClass.toClass();
		Object o=c.newInstance();
		Method method=o.getClass().getMethod("execute", new Class[]{});
		//调用字节码生成类的execute方法
		method.invoke(o, new Object[]{});
	}

}


javassist还有一个比较常见的用途是AOP,比如对一些类统一加权限过滤,加日志监控等等。
下面示例如何使用javassist来进行AOP拦截处理

我们对上面例子的JavassistClass类的getName()方法进行拦截前置处理

package com.taobao.relationrecommend.web.util;

import java.lang.reflect.Method;

import javassist.util.proxy.MethodFilter;
import javassist.util.proxy.MethodHandler;
import javassist.util.proxy.ProxyFactory;

public class JavassistLearn{
	
	
	public static void main(String[] args) throws Exception{
		ProxyFactory factory=new ProxyFactory();
		//设置父类,ProxyFactory将会动态生成一个类,继承该父类
		factory.setSuperclass(JavassistClass.class);
		//设置过滤器,判断哪些方法调用需要被拦截
		factory.setFilter(new MethodFilter() {
			@Override
			public boolean isHandled(Method m) {
				if(m.getName().equals("getName")){
					return true;
				}
				return false;
			}
		});
		//设置拦截处理
		factory.setHandler(new MethodHandler() {
			@Override
			public Object invoke(Object self, Method thisMethod, Method proceed,
					Object[] args) throws Throwable {
				//拦截后前置处理,改写name属性的内容
				//实际情况可根据需求修改
				JavassistClass o=(JavassistClass) self;
				o.setName("haha");
				return proceed.invoke(self, args);
			}
		});
		
		Class<?> c=factory.createClass();
		JavassistClass object=(JavassistClass) c.newInstance();
		System.out.println(object.getName());
		
	}

}





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值