上一章节《Spring4基础二六-AOP篇-AspectJ介绍》
如果文中有纰漏,请多多指正!!!
一.复习切入点表达式
常用切入点表达式execution,具体格式如下:
execution( modifiers-pattern? //访问修饰符 ret-type-pattern //返回值类型(必须有) declaring-type-pattern? //全限定性类名(类路径匹配) name-pattern(param-pattern)//方法名(参数名)(必须有) throws-pattern? //抛出异常类型 )? 通配符匹配 0 个 1 个
切入点表达式其实就是方法签名。切入点表达式分5部分组成,其中加?符号的可以省略,所以以下是必须要有的:
- ret-type-pattern //返回值类型(必须有)
- name-pattern(param-pattern)//方法名(参数名)(必须有)
二.环境搭建
因为AspecJ是一个独有的框架,Spring也将其引入到了自己的框架中,所以需要引入对AspectJ支持的jar包。
- spring-aspects-4.2.1.RELEASE.jar
- com.springsource.org.aspectj.weaver-1.6.8.RELEASE.jar
三.XML配置演示
- 1.定义接口
//目标方法public class ServiceDemoImpl implements IServiceDemo{ @Override public void doExceptionWork(int a) { int r = 1/a; System.out.println("doExceptionWork执行。r = "+ r); } @Override public String nothing(String str) { System.out.println("nothing执行"); return "返回 String"; } }
- 2.定义切面
定义一个POJO(Plain Ordinary Java Object)简单的Java对象,将其作为切面,其中定义的普通方法将作为不同的通知方法出现。首先要了解下通知的方法定义:
-
- 前置通知方法
- 可以包含一个JoinPoint类型的参数,通过参数可以获取目标对象等信息。(主要)
- 举例
- 前置通知方法
public void before(){}或者public void before(JoinPoint jp){}
-
- 后置通知方法
-
-
- 可以包含一个JoinPoint类型的参数,通过参数可以获取目标对象等信息。
- 也可以包含一个用于接收目标方法返回值的变量(最好定义成Object,因返回值可以是任意类型)。(主要)
- 举例
-
public void after(){}或者public void after(JoinPoint jp){} 或者public void after(Object result){}
-
- 环绕通知方法
-
-
- 方法要有返回值,Object类型(如果目标方法有返回值,该返回值就是目标方法的返回值)。
- 可以包含一个JoinPoint类型的参数,通过参数可以获取目标对象等信息。
- 也可以包含ProceedingJoinPoint类型参数,主要用于执行目标方法。(主要)
- 举例
-
public Object round(){}或者public Object round(ProceedingJoinPoint pj){} 或者public Object round(JoinPoint jp){}
-
- 异常通知方法
-
-
- 可以包含一个JoinPoint类型的参数,通过参数可以获取目标对象等信息。
- 可以包含一个Throwable类型的参数,通过参数异常信息。(主要)
- 举例
-
public void getThrow(){}或者public void getThrow(Throwable tb){}或者public Object getThrow(JoinPoint jp){}
-
- 最终通知方法
-
-
- 可以包含一个JoinPoint类型的参数,通过参数可以获取目标对象等信息。
- 举例
-
public void afterFinal(){}或者public void afterFinal(JoinPoint jp){}
了解了通知的定义后,我们进行切面的定义
//切面定义public class MyAspectXMl { /** * 前置通知 */ public void beforeAdvice(JoinPoint jp){ System.out.println("前置通知..."+jp.toString()+",方法签名"+jp.getSignature()); } /** * 环绕通知 * 如果目标方法有返回值,则该方法的返回值就是目标方法的返回值 * @throws Throwable */ public Object roundAdvice(ProceedingJoinPoint point) throws Throwable{ System.out.println("环绕通知 开始..."); Object obj = point.proceed();//执行目标方法 if(obj instanceof String){ return (String)obj + "环绕通知"; } System.out.println("环绕通知 结束..."); return obj; } /** * 后置通知 * Object obj 为目标方法返回值的变量 * @throws Throwable */ public void afterAdvice(Object obj) throws Throwable{ System.out.println("后置通知 ..."); } /** * 异常通知 * Throwable tb 异常信息捕捉 * @throws Throwable */ public void throwAdvice(Throwable tb) throws Throwable{ System.out.println("异常通知 ...,异常信息:"+tb.getMessage()); } /** * 最终通知 * @throws Throwable */ public void finallyAdvice(JoinPoint jp) throws Throwable{ System.out.println("最终通知..."); }}
- 3.xml配置
4.测试
@Testpublic void test1() { ClassPathXmlApplicationContext application = new ClassPathXmlApplicationContext("applicationContext.xml"); //获取代理对象 IServiceDemo bean = (IServiceDemo)application.getBean("serviceTarget"); bean.doExceptionWork(1); bean.nothing("3"); application.close();//销毁}
-
- 正常测试
bean.doExceptionWork(1);//测试方法doExceptionWork执行。r = 1前置通知...execution(String com.spring.aop.demo1.IServiceDemo.nothing(String)),方法签名String com.spring.aop.demo1.IServiceDemo.nothing(String)环绕通知 开始...nothing执行最终通知...后置通知 ...
-
- 异常测试
bean.doExceptionWork(0);//测试方法异常通知 ...,异常信息:/ by zero