Spring——AOP(面向切面编程)@AspectJ注解方式
一、什么是AOP?
AOP: (Aspect Oriented Programming)即面向切面编程。
试想这样的场景:项目中需要在业务方法执行完打印日志记录。最笨的办法就是在每个方法核心业务执行完后加入日志打印程序语句,但如果项目浩大,这样工程量是巨大的,而且若要求对日志打印部分进行修改,则又要对每个方法里的打印语句进行修改,这简直是灾难。好点的办法就是把打印日志的语句封装起来,抽取出来专门顶一个打印日志的方法,这样会把日志打印语句从核心业务中分离出来,在业务语句执行后调用日志打印的方法即可,这样工作量小了不少,而且耦合度也变低了。但是,因为要调用方法,还是有一定耦合度的,后来有人就提出了AOP,从而彻底地使两者分离。
二、基于@AspectJ注解方式实现AOP:
1.首先要在配置文件中添加<aop:aspectj-autoproxy/>,启动对@AspectJ注解的支持。
<!-- 启动对@AspectJ注解的支持 --> <aop:aspectj-autoproxy/>
2.定义切面类(所谓切面类,就是定义一些围绕核心业务方法的日志打印之类的方法,去切入核心业务,注解用@AspectJ表示切面类。再在这些定义的处理方法上用@Before,@After,@Around等注解限定它们切入哪些业务方法。
@Component @Aspect //表示这是一个切面类,里面的方法都是像打印日志等围绕业务方法的方法 public class AopLog { //方法执行前调用,插入com.zywang.services.impl包下所有业务方法 @Before("execution (* com.zywang.services.impl.*.*(..))") public void printLog() { System.out.println("业务方法执行前日志。"); } //方法执行后调用,插入 com.zywang.services.impl包下所有方法 @After("execution (* com.zywang.services.impl.*.*(..))") public void MyMethod() { System.out.println("业务方法执行后日志"); } //方法执行的前后调用,前后都插入。 @Around("execution (* com.zywang.services.impl.*.*(..))") public Object MyMethod(ProceedingJoinPoint point) throws Throwable{ System.out.println("begin around"); Object object = point.proceed(); System.out.println("你们都可以来插入我"); return object; } //方法运行出现异常时调用,出现异常后插入。 @AfterThrowing(pointcut = "execution (* com.zywang.services.impl.*.*(..))",throwing = "ex") public void MyMethod(Exception ex){ System.out.println("afterThrowing"); System.out.println(ex); } }
另外:我们可以声明切入点(Pointcut),所谓切入点就是给比较啰嗦的切入表达式起个简洁的名字,在多处使用的时候用简洁的名字,使之方便。
如下例子,在注解@pointcut下定义一个私有的,无返回值,无参数的方法,就可以取代括号里复杂的切入表达式了。
// 使用@Pointcut Annotation 时指定切入点表达式 @pointcut("execution * transfer(..)") // 使用一个返回值为void,方法体为空的方法来命名切入点 private void anyOldTransfer(){} // 使用上面定义的切入点 @AfterReturning(pointcut="anyOldTransfer()", returning="reVal") public void writeLog(String msg, Object reVal){ ... }