AOP--注解实现通知
AOP关于通知的注解
@Before:前置通知。被拦截方法执行之前执行。
@AfterReturning:跑完通知。被拦截方法正常完成之后执行,异常时不执行。
@AfterThrowing:异常通知。被拦截方法发生异常时执行。
@Around:环绕通知。融合了@Before、@AfterReturning、@AfterThrowing,还有类似@After的通知(演化为最终通知)
代码实现:
C1Target 目标类
C2AdviceAround 环绕通知类
C3AdviceBefore 四大通知类
Test注解AOP 测试类(通过注释掉@Component注解 ,实现两种通知测试)
MAVEN环境下配置文件
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd"> <!-- 开启自动扫描 --> <context:component-scan base-package="demo03.aspect"/> <!-- 开启aspectj自动代理 --> <aop:aspectj-autoproxy></aop:aspectj-autoproxy> </beans>
package demo03.aspect; import org.springframework.stereotype.Component; @Component public class C1Target { public String save(String arg1, int arg2) { // System.out.println(10 / 0); System.out.println(arg1 + ":" + arg2 + ":保存成功"); return "【success】"; } }
package demo03.aspect; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.springframework.stereotype.Component; //@Component @Aspect public class C2AdviceAround { @Around(value = "bean(c1*)") public void doAround(ProceedingJoinPoint pjp) { // 【proceeding/proceed:继续做】 System.out.println("1.前置通知@Before"); try { Object ob = pjp.proceed(); System.out.println("2.跑完通知@AfterReturning:" + ob); } catch (Throwable e) { System.out.println("3.异常通知@AfterThrowing:" + e.getMessage()); } System.out.println("4.最终通知(异常了也通知),类似于@After,但是执行时机更靠后。"); } }
package demo03.aspect; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.annotation.*; import org.springframework.stereotype.Component; @Component @Aspect public class C3AdviceBefore { @Before(value = "bean(c1*)") public void doBefore(JoinPoint jp) { System.out.println("---前置通知@Before---"); // 目标类 String strClass = jp.getTarget().getClass().getName(); System.out.println("获取目标对象:" + strClass); // 目标函数参数 Object[] objs = jp.getArgs(); for (int i = 0; i < objs.length; i++) { System.out.println("目标函数参数[" + i + "]:" + objs[i]); } // 目标函数的方法签名:String ah.demo09aop.p4anno.C1Target.save(String,int) System.out.println("获取目标函数的方法签名:" + jp.getSignature()); } @AfterReturning(pointcut = "bean(c1*)", returning = "oRet") public void testAfterReturn(JoinPoint jp, Object oRet) { System.out.println("---跑完通知@AfterReturning---" + oRet); } @AfterThrowing(pointcut = "bean(c1*)", throwing = "e") public void doThrow(JoinPoint jp, Throwable e) { System.out.println(e.getMessage()); System.out.println("---异常通知@AfterThrowing---"); } @After(value = "bean(c1*)") public void doAfter(JoinPoint jp) { System.out.println("---后置通知@After---"); } }
package demo03.aspect; import org.springframework.context.*; import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.context.*;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Test注解AOP {
@org.junit.Test
public void test环绕通知() {
ApplicationContext ac = new ClassPathXmlApplicationContext("application.xml");
C1Target target = (C1Target) ac.getBean("c1Target");// 类名首字母小写
target.save("save方法参数名", 998);
((ClassPathXmlApplicationContext) ac).close();
}
}
正常运行结果:
---前置通知@Before---
获取目标对象:demo03.aspect.C1Target
目标函数参数[0]:save方法参数名
目标函数参数[1]:998
获取目标函数的方法签名:String demo03.aspect.C1Target.save(String,int)
save方法参数名:998:保存成功
---后置通知@After---
---跑完通知@AfterReturning---【success】
有异常时运行结果:
---前置通知@Before---
获取目标对象:demo03.aspect.C1Target
目标函数参数[0]:save方法参数名
目标函数参数[1]:998
获取目标函数的方法签名:String demo03.aspect.C1Target.save(String,int)
---后置通知@After---
/ by zero
---异常通知@AfterThrowing---