AspectJ是一个基于Java语言的AOP框架,Spring2.0开始,Spring AOP引入对Aspect的支持,AspectJ扩展了Java语言,提供了一个专门的编译器,在编译时提供横向代码的织入
首先明白一下概念,知道这是个什么玩意之后,在去敲代码,容易理解,编程不在于敲,在于理解!!!!
第一步 导入jar包
第二步,写XML 切记这几个命名空间一定到导
第三步 写Service 和实现类
最后 最重要的一个类 配置切面类
import org.aspectj.lang.JoinPoint; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.After; import org.aspectj.lang.annotation.AfterReturning; import org.aspectj.lang.annotation.AfterThrowing; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.aspectj.lang.annotation.Pointcut; import org.springframework.stereotype.Component; //1.配置bean 配置切面对象 //2.配置aop指定一个切面类 @Component @Aspect public class MyAspect { //声明一个公共的切入点 @Pointcut("execution(* com.lq.service.impl.UserServiceImpl.*(..))") public void myPointcut() {} //3.声明前置通知 @Before("myPointcut()") public void myBefore(JoinPoint jp) { System.out.println("前置通知:"+jp.getSignature().getName());//连接点方法名 } //4.声明后置通知 /** * 后置通知获取service方法执行后的返回值 * @param jp * @param retvalue service方法执行的返回值,如果写了返回值,需要在xml中配置returning */ @AfterReturning(pointcut = "myPointcut()",returning = "retvalue") public void myAfterReturning(JoinPoint jp,Object retvalue) { System.out.println("3.后置通知..." + jp.getSignature().getName()); System.out.println("返回值:" + retvalue); } //环绕通知 @Around("myPointcut()") public Object myAround(ProceedingJoinPoint pjp) { System.out.println("2.环绕通知...开启事务..." + pjp.getSignature().getName()); //放行 Object proceed=null; try { proceed = pjp.proceed(); System.out.println(proceed); System.out.println("4.环绕通知....提交事务..."); } catch (Throwable e) { e.printStackTrace(); System.out.println("异常消息"+e.getMessage()); System.out.println("回滚事务"); } return proceed; } //异常通知 @AfterThrowing(pointcut = "myPointcut()",throwing = "e") public void myAfterThrowing(JoinPoint jp,Throwable e) { System.out.println("异常通知..."+jp.getSignature().getName()); } //最终通知 @After("myPointcut()") public void myAfter(JoinPoint jp){ System.out.println("最终通知..." + jp.getSignature().getName()); } }演示一下 怎么用 这里我故意抛出一个异常 你们就知道强大之处了。在ServieImpl实现类 加上一个算术异常
编写测试类
从下图中 我们很清晰看到 他首先先执行了环绕通知 后面执行了前置通知 然后打印了一句话 接着抛出了那个算术异常。在看看后面
从下图看出 他执行了环绕的回滚 所以发生异常 它就进行了回滚 所以这里就很形象展示了 为什么AOP有事务处理功效呢。接下来我们在重点看看 他们的执行顺序 这个是重点!!!!
AOP通知的一个执行顺序在下面,我们要牢记。
1.service方法有返回值 + 无异常 + XML
*************************************** 1.前置通知...deleteUser 2.环绕通知...开启事务...deleteUser 通过id删除用户 3.后置通知...deleteUser 返回值:1 4.环绕通知....提交事务... 最终通知...deleteUser **************************************
2.service方法有返回值 + 无异常 + 注解
************************************** 2.环绕通知...开启事务...deleteUser 1.前置通知...deleteUser 通过id删除用户 4.环绕通知....提交事务... 最终通知...deleteUser 3.后置通知...deleteUser 返回值:1 **************************************
3.service方法没有返回值 + 无异常 + XML
*************************************** 1.前置通知...deleteUser 2.环绕通知...开启事务...deleteUser 删除用户。。。。 3.后置通知...deleteUser 返回值:null 4.环绕通知....提交事务... 最终通知...deleteUser ***************************************
4.service方法没有返回值 + 无异常 + 注解
**************************************** 2.环绕通知...开启事务...deleteUser 1.前置通知...deleteUser 删除用户。。。。 4.环绕通知....提交事务... 最终通知...deleteUser 3.后置通知...deleteUser 返回值:null
***************************************
最后,双手奉献上 我研究的AOP web用法。
是的 你没有看错,当程序跑的时候,你发起请求,就能看到请求该方法路径 参数 IP地址等信息都可以被打印出来。
好了 开始总结 这么多注解 相信刚学的人 有点茫然了都。
@Aspect:声明切面,修饰切面类,从而获得 通知。
通知的注解:
@Before:前置
@AfterReturning:后置
@Around:环绕
@AfterThrowing:抛出异常
@After:最终
切入点注解:
@PointCut,修饰方法private void xxx(){} 之后通过“方法名”获取切入点引用 示例
//声明一个公共的切入点 @Pointcut("execution(* com.lq.service.impl.UserServiceImpl.*(..))") public void myPointcut() {} //3.声明前置通知 @Before("myPointcut()") public void myBefore(JoinPoint jp) { System.out.println("前置通知:"+jp.getSignature().getName());//连接点方法名 }讲到这里,AOP算是结束了,算是被它搞死,,,我记得刚学时候一点都不喜欢AOP 直接三倍速度跳过,但是后面项目发现,用AOP地方挺多,而且发现这个玩意挺方便的,于是 又回头来深入学习一下。哈哈 虽然还是有一点点痛苦,但是 切面还是要切的、