使用AspectJ在编译期增强字节码实现AOP
1.IDEA搭建aspectj开发环境
从http://www.eclipse.org/aspectj/downloads.php上下载aspectj-1.8.6.jar
使用命令java -jar aspectj-1.8.6.jar安装aspectj
如果未安装AspectJ插件请先安装AspectJ Support和Spring AOP/@AspectJ插件
在IDEA中进入settings->Compiler->Java Compiler Use compiler选择Ajc
在Ajc options中,path to ajc compiler中选择aspectjtools.jar的安装路径应用此设置
2.编写类
public class Hello { public void sayHello() { System.out.println("say hello"); } public static void main(String[] args) { Hello hello = new Hello(); hello.sayHello(); } }编写切面
public aspect TxAspect { pointcut callPointCut(): call(void aop.Hello.sayHello()); void around():callPointCut() { System.out.println("开始事务"); proceed(); System.out.println("结束事务"); } }运行Hello.java,结果为:
开始事务
say hello
结束事务
从结果来看,AOP已经生效了,下面我们来看看class文件是如何在不修改源文件的情况下增强Hello类的功能的
public class Hello { public Hello() { } public void sayHello() { System.out.println("say hello"); } public static void main(String[] args) { Hello hello = new Hello(); sayHello_aroundBody1$advice(hello, TxAspect.aspectOf(), (AroundClosure)null); } }TxAspectJ.class
@Aspect public class TxAspect { static { try { ajc$postClinit(); } catch (Throwable var1) { ajc$initFailureCause = var1; } } public TxAspect() { } @Around( value = "callPointCut()", argNames = "ajc$aroundClosure" ) public void ajc$around$aop_TxAspect$1$88992c11(AroundClosure ajc$aroundClosure) { System.out.println("开始事务"); ajc$around$aop_TxAspect$1$88992c11proceed(ajc$aroundClosure); System.out.println("结束事务"); } public static TxAspect aspectOf() { if(ajc$perSingletonInstance == null) { throw new NoAspectBoundException("aop_TxAspect", ajc$initFailureCause); } else { return ajc$perSingletonInstance; } } public static boolean hasAspect() { return ajc$perSingletonInstance != null; } }上面的class文件就是AspectJ的静态代理,它会在编译阶段将Aspect织入Java代码中,运行的时候就是增强的Hello类,TxAspect中的proceed方法就是回调执行被代理类的方法。