aspectj 通过前置,后置,异常通知注解,表述 spring AOP,测试结构图如下:
aop test结构图为:
如果看着不清晰,可参看
http://on-img.com/chart_image/5b0ccc1ae4b0843e3bded605.png
下面是具体的代码测试:
1、 接口定义
package com.msyd.spring.aop.aspectj;
/**表演者(接口)*/
public interface Performer {
public void perform();
}
2 、目标对象
package com.msyd.spring.aop.aspectj;
/**歌手(目标对象)*/
public class Singer implements Performer {
public void perform() {
System.out.println("action:i am a singer!i speak for myself ! ");
}
}
3 、切面类里定义通知
package com.msyd.spring.aop.aspectj;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
/**观众(切面),可以在歌手表演过程中(目标对象调用过程中,运行时)织入通知。在演员表演之前,做好,关掉手机,演员演的好的时候,观众则鼓掌;演的不好则退票,演出完毕,观众开机@after,回家*/
@Aspect
public class Audience {
@Pointcut("execution(* com.msyd.spring.aop.aspectj.Performer.perform())")
public void watch() {
}
/**
* aspectj表达式:切入点表达式
* 前置通知可以看方法名称,可以获取目标对象和代理对象,但是他们指向的是同一个内存地址,
* 所以通过打印并不能看出差异,只能通过断点调试才能发现。
* */
@Before("watch()")
public void takeSeat(JoinPoint jp) {
System.out.println("sitDown as BeforeAdvice,proxy interface.methodName is:" + jp.getSignature().getName());
System.out.println("proxyObject is :" + jp.getThis() + ",targetObject:" + jp.getTarget());
}
/**表演前关机*/
@Before("watch()")
public void turnOffPhoneBeforePerform() {
System.out.println("turnOffPhone()");
}
/**后置通知,returning 指定接收返回值得参数名
*
* */
@AfterReturning(pointcut = "watch()", returning = "ret")
public void Applaud(JoinPoint jp, Object ret) {
System.out.println("Applaud and ret=" + ret);
}
@AfterThrowing(pointcut = "watch()", throwing = "e")
public void payOff(JoinPoint jp, Exception e) {
System.out.println("演出失败 and payOff and e=" + e.getMessage());
}
@After(value = "watch()")
public void goHome(JoinPoint jp) {
System.out.println("goHome," + jp.toString());
}
}
4、apectj.xml定义
<?xml version="1.0"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.1.xsd
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<!-- 观众(切面) -->
<bean class="com.msyd.spring.aop.aspectj.Audience"/>
<!--歌手(目标对象) -->
<bean id="singer" class="com.msyd.spring.aop.aspectj.Singer"/>
<!-- aop自动代理 -->
<aop:aspectj-autoproxy />
</beans>
5 、测试类编写 app.java
package com.msyd.spring.aop.aspectj;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class App {
public static void main(String[] args) {
ApplicationContext ac = new ClassPathXmlApplicationContext("aspectj.xml", App.class);
Performer P = (Performer) ac.getBean("singer");//获取目标对象,自动代理可以用接口来接收
P.perform();
}
}
6.1、 test调用方法成功结果
sitDown as BeforeAdvice,proxy interface.methodName is:perform
proxyObject is :com.msyd.spring.aop.aspectj.Singer@79ca92b9,targetObject:com.msyd.spring.aop.aspectj.Singer@79ca92b9
turnOffPhone()
action:i am a singer!i speak for myself !
Applaud and ret=null
goHome,execution(void com.msyd.spring.aop.aspectj.Performer.perform())
#6.2 、test调用方法失败结果
turnOffPhone()
sitDown as BeforeAdvice,proxy interface.methodName is:perform
proxyObject is :com.msyd.spring.aop.aspectj.Singer@79ca92b9,targetObject:com.msyd.spring.aop.aspectj.Singer@79ca92b9
action:i am a singer!i speak for myself !
演出失败 and payOff and e=null
goHome,execution(void com.msyd.spring.aop.aspectj.Performer.perform())
由以上结果可以看出,aspectj的注解:
@After 表示不管成功或者失败,调用方法后都会通知
@AfterThrowing 异常通知
@AfterReturning 后置通知
@Before 前置通知
下一节我们一起学习aspectj的环绕通知。