AOP系列文章:
Spring AOP:http://ray-yui.iteye.com/blog/2024759
CGLIB:http://ray-yui.iteye.com/blog/2026426
Javassist:http://ray-yui.iteye.com/blog/2029261
Javassist是一个强大的高性能的代码生成包,和CGLIB一样成为众多框架的动态代理解决方案,和CGLIB同样拥有不需要实现接口即可进行动态代理的特点,而且还支持动态生成Java代码,动态实现代理逻辑等强大功能
使用Javassist生成动态代理可以使用两种方式,一种是使用代理工厂创建,和普通的JDK动态代理和CGLIB类似,另一种则可以使用动态代码创建
使用工厂创建动态代理例子
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()); } }
上述代码和JDK动态代理和CGLIB的使用方式非常相似,但创建动态代理效率不如JDK动态,以下为动态字节生成动态代理例子
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()); } }
上述例子中使用Javassist的API成功组织出代理类的一个子类,可以看出添加构造函数,增加属性,增加方法,内容都是使用字符串类型即可完成,通过Javassist强大的字节生成能力可以达到动态增加类和实现动态代理的功能,Javassist的动态生成类功能除了应用在动态代理还有很多其他地方可以使用,请读者在实际项目场景灵活运用