概述在学习spring aop过程中,发现有个怎么都绕不过去的坎,就是AspectJ的使用。少了这一部分,一些spring aop的源码总觉得少了点什么,看不大懂。所以接下来会写几篇关于AspectJ的入门使用。
安装示例代码1、首先,下载最新的稳定版本(我自己下的是AspectJ 1.9.2, Released 24 Oct 2018 版本)aspectj-1.9.2.jar
www.eclipse.org/aspect...
2、安装
aspectJ的安装很简单,运行 java -jar aspectj-1.9.2.jar 然后选下jdk路径及最终aspectj要安装(AspecJ安装路径)到哪里就好
3、安装最后,会提示你要配置环境变量了
按照环境配下PATH变量 和 CLASSPATH变量就好
export PATH=
执行 ajc -argfile telecom/billing.lst
5、运行示例
java telecom.BillingSimulation6、运行结果
[Items [id=1, name=台式机, price=3000.0, pic=null, createtime=Tue Oct 03 23:22:36 CST 2017, detail=该电脑质量非常好!!!!111], Items [id=2, name=笔记本, price=7000.0, pic=null, createtime=Tue Oct 03 23:23:06 CST 2017, detail=笔记本性能好,质量好!!!!!], Items [id=3, name=背包, price=1200.0, pic=null, createtime=Tue Oct 03 23:23:21 CST 2017, detail=名牌背包,容量大质量好!!!!]]
示例总结简单总结下:
1)安装配置aspectJ环境
2)使用 ajc -argfile 编译类
3)运行编译后的字节码
上述的例子是aspectJ 官方的例子 ,为了说明如何使用aspectJ的使用,我们看另一个例子
另一个例子知道如何运行aspectJ给的官方示例后,我们继续学习官网给的另一个例子,例子路径
${aspectJ 路径}/doc/examples/tjp/Demo.java
我们先来看看原始类
public class Demo { static Demo d; public static void main(String[] args){ new Demo().go(); } void go(){ d = new Demo(); //调用foo方法 d.foo(1,d); //调用bar方法 System.out.println(d.bar(new Integer(3))); } void foo(int i, Object o){ //打印foo System.out.println("Demo.foo(" + i + ", " + o + ")n"); } String bar (Integer j){ System.out.println("Demo.bar(" + j + ")n"); return "Demo.bar(" + j + ")"; }}再来看看一个随着Demo.java一起被 ajc编译的特殊的类GetInfo.java:
package tjp;import org.aspectj.lang.JoinPoint;import org.aspectj.lang.reflect.CodeSignature;aspect GetInfo { static final void println(String s){ System.out.println(s); } pointcut goCut(): cflow(this(Demo) && execution(void go())); pointcut demoExecs(): within(Demo) && execution(
这里说明一下几点:
GetInfo.java 含有的特殊关键词GetInfo.java含有很多特殊的关键词,这些关键词java是无法识别的,需要通过ajc编译才能织入到字节码中
切入点表达式spring的切入点表达式我们非常熟悉,使用aspectJ时,也需要配置切入点,需要配置有哪些方法需要被切入
//表示Demo类的go方法调用过程中的方法需要被增强pointcut goCut(): cflow(this(Demo) && execution(void go()));//每一个Demo类定义的方法pointcut demoExecs(): within(Demo) && execution(
demoExecs() 以及 !execution(* go()) && goCut() 单独有一个不够么?
1)demoExecs()表示拦截Demo类的所有方法,如果不加后面的限制,会同时拦截main方法,以及go()方法
2)如果只有!execution(* go()) && goCut(),直接编译时候会报错(warning)执行后直接会报java.lang.StackOverflowError
3)如果只有!execution(* go()) && goCut(),可以执行,但是只会拦截go方法
thisJoinPointStaticPart 和 thisJoinPointthisJoinPoint 包含了关于当前切入点的一些信息(通过反射获取的)
thisJoinPointStaticPart 包含一些静态信息,参考官方文档
通过配置切入点,我们实现了不改变Demo.java源码的前提下,往Demo.java方法的前后插入了一段代码。
与Spring 切面写法的对比对比下之前在学习Spring时候,配置的切面
//声明这是一个组件@Component//声明这是一个切面Bean@Aspect@Slf4jpublic class ServiceAspect { //配置切入点,该方法无方法体,主要为方便同类中其他方法使用此处配置的切入点 @Pointcut("execution(
总结下初步了解了aspectJ的使用,我们可以了解以下几点:
1)aspectJ的使用是在编译期,通过特殊的编译器可以在不改变代码的前提下织入代码(当然能不能在运行期,我还没有确认)
2)aspectJ的使用,也是配置切入点、通知