刚开始接触java,总是听到AOP技术也就是面向切面编程技术,一直很迷糊,它到底是什么,干什么用的,实现原理是什么。今天在这里做个小结。
首先介绍一下AOP技术的由来:
在我们的业务系统中,有时候需要用业务系统中的”某些代码”去执行一些公共的动作,比如写日志、数据库连接管理、事务管理。那么这样就需要我们在很多方法中添加重复代码,这样使得代码重复率过高,也不好维护。那么我们想到的是要求每个Action都继承框架提供好的BaseAction,然后实现excute方法来实现。不过,这样的方式缺乏灵活性,那就是我们每个Action都需要写一个类来完成,对于复杂的系统,就需要写太多这样的类,因此,我们期望有一种动态的方式来代理操作,于是动态代理机制就出现了,AOP技术其实也是字节码增强技术,JVM提供的动态代理追根到底也是字节码增强技术。
字节码增强技术的实现原理:
字节码增强技术的实现有两种方式:
一种是通过创建原始类的一个子类,也就是动态创建的一个新的类继承原始类。
二种是很暴力的方式,直接修改Class字节码。
实现字节码增强技术的步骤:
一是在内存中获取原始的字节码,通过一些开源的API修改它的byte[]数组,得到一个新的byte[]。
二将这个新的byte[]数组写到PermGen区域,也就是加载新的byte[]替换原来的Class字节码。
实现原理和简介就介绍到这里,下面我们来个例子。
我们采用的开源api 为javaassit的API来实现字节码增强技术。
我们构造一个Transformer方法,它需要实现接口ClassFileTransformer,并实现transform方法,代码如下:
1、修改class字节码
public class TestTransformer implements ClassFileTransformer { @Override public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException { System.out.println("load class:"+className); //判断是否是需要我们切得目标类 if("/targetclass".equals(className)){ CtClass ctClass=ClassPool.getDefault().get(className.replace(‘/‘, ‘.‘)); //获取需要切得目标方法 CtMethod ctMethod=ctClass.getDeclaredMethod("display1"); //插入需要在此之前执行的方法 ctMethod.insertBefore("name=\"XXXX\";"); //插入需要在display1之后执行的方法 ctMethod.insertAfter("System.out.println(value);"); return ctClass.toBytecode(); } // TODO Auto-generated method stub return null; } }
2、注册到Instrumentation中,加载新的class字节码
public class InstForTransformer{ public static void premain(String agentArgs,Instrumentation instP){ instP.addTransformer(new TestTransformer()); } }
如果注册成功,那么在JVM加载用户class是,就会调用对应的TestTransformer类的transform方法来获得修改后的字节码,达到修改字节码的目的。发现很多java教程都没有这方面的讲解,那就我来弥补一下吧