高级字节码生成工具 — Javassist

[size=large]
AOP系列文章:
Spring AOP:[url]http://ray-yui.iteye.com/blog/2024759[/url]
CGLIB:[url]http://ray-yui.iteye.com/blog/2026426[/url]
Javassist:[url]http://ray-yui.iteye.com/blog/2029261[/url]
[/size]
[size=large]
[b][color=red]Javassist是一个强大的高性能的代码生成包[/color][/b],和CGLIB一样成为众多框架的动态代理解决方案,和CGLIB同样拥有不需要实现接口即可进行动态代理的特点,而且还[b][color=red]支持动态生成Java代码,动态实现代理逻辑等强大功能[/color][/b]
[/size]
[size=large]
使用Javassist生成动态代理可以使用两种方式,[b][color=red]一种是使用代理工厂创建,和普通的JDK动态代理和CGLIB类似,另一种则可以使用动态代码创建[/color][/b]
[/size]
[size=large]
[b][color=red]使用工厂创建动态代理例子[/color][/b]
[/size]

public class TestMain {
@SuppressWarnings("unchecked")
@Test
public void testJavassistFactoryProxy() throws Exception {
// 创建代理工厂
ProxyFactory proxyFactory = new ProxyFactory();

// 设置被代理类已实现接口(可选)
// proxyFactory.setInterfaces(new Class[] {});

// 设置被代理类的类型
proxyFactory.setSuperclass(RayTest.class);

// 创建代理类型的Class
Class<ProxyObject> proxyClass = proxyFactory.createClass();

// 注意若然父类没有无参构造函数,需要使用createClass方法的重載
// RayTest proxyTest = (RayTest) proxyFactory.create(new Class[] {
// Integer.class }, new Object[] { 0 });

RayTest proxyTest = (RayTest) proxyClass.newInstance();

((ProxyObject) proxyTest).setHandler(new MethodHandler() {

// 真实主題
RayTest test = new RayTest();

@Override
public Object invoke(Object self, Method thisMethod,
Method proceed, Object[] args) throws Throwable {
String before = "before ";
Object str = thisMethod.invoke(test, args);
String after = " after";
return before + str + after;
}
});

Assert.assertEquals("before execute after", proxyTest.execute());
}
}

[size=large]
[b][color=red]上述代码和JDK动态代理和CGLIB的使用方式非常相似,但创建动态代理效率不如JDK动态,以下为动态字节生成动态代理例子 [/color][/b]
[/size]

public class TestMain {

@SuppressWarnings("unchecked")
@Test
public void testJavassistDenfinClass() throws Exception {
// 创建类池,true为使用默认路径
ClassPool classPool = new ClassPool(true);

String className = RayTest.class.getName();
CtClass ctClass = classPool.makeClass(className + "JavassitProxy");

// 添加接口,可选
// ctClass.addInterface(classPool.get(RayTestInterface.class.getName()));

// 添加超类
ctClass.setSuperclass(classPool.get(RayTest.class.getName()));

// 添加默认构造函数
ctClass.addConstructor(CtNewConstructor.defaultConstructor(ctClass));

// 添加屬性
ctClass.addField(CtField.make("public " + className + " real = new "
+ className + "();", ctClass));

// 添加方法,里面进行动态代理logic
ctClass.addMethod(CtNewMethod
.make("public String execute(){ return \"before \" + real.execute() + \" after\";}",
ctClass));

Class<RayTest> testClass = ctClass.toClass();
RayTest test = testClass.newInstance();
Assert.assertEquals("before execute after", test.execute());

}
}

[size=large]
上述例子中使用Javassist的API成功组织出代理类的一个子类,[b][color=red]可以看出添加构造函数,增加属性,增加方法,内容都是使用字符串类型即可完成[/color][/b],通过Javassist强大的字节生成能力可以达到动态增加类和实现动态代理的功能,[b][color=red]Javassist的动态生成类功能除了应用在动态代理还有很多其他地方可以使用,请读者在实际项目场景灵活运用[/color][/b]
[/size]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值