通知简介
前置通知(Before advice)
在目标方式执行之前执行,所以获取不到目标方法执行后的返回值
后置通知(After returning advice)
- 后置通知可以获取到目标方法的返回值
- 当目标方法抛出异常,后置通知将不再执行
异常通知(After throwing advice)
目标方法发生 异常时执行
最终通知(finally advice)
无论目标方法是否抛出异常都将执行
环绕通知(Around advice)
通过joinPoint.proceed()控制目标方法的执行
实例
目标类:PersonDaoImpl.java
public class PersonDaoImpl implements PersonDao{
public String savePerson() {
// int a = 1/0;
System.out.println("save person");
return "aaa";
}
}
切面:Transaction.java
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
//切面
public class Transaction {
/*
* 前置通知
* 在目标方法执行之前
* joinPoint :连接点
*/
public void beginTransaction(JoinPoint joinPoint){
String methodName = joinPoint.getSignature().getName();
System.out.println("连接点的名称:"+methodName);
System.out.println("目标类:"+joinPoint.getTarget().getClass());
System.out.println("begin transaction");
}
/**
* 后置通知
* 在目标方法执行之后
*/
public void commit(JoinPoint joinPoint,Object val){
System.out.println("目标方法的返回值:"+val);
System.out.println("commit");
}
/**
* 最终通知
*/
public void finallyMethod(){
System.out.println("finally method");
}
/**
* 异常通知
* 接受目标方法抛出的异常
*/
public void throwingMethod(JoinPoint joinPoint,Throwable ex){
System.out.println(ex.getMessage());
}
/**
* 环绕通知
* joinPoint.proceed();这个代码如果在环绕通知中不写,则目标方法不再执行
*/
public void aroundMethod(ProceedingJoinPoint joinPoint) throws Throwable{
System.out.println("环绕通知");
joinPoint.proceed();//调用目标方法
}
}
配置文件:applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">
<bean id="personDao" class="com.kelly.spring.aop.xml.transaction.PersonDaoImpl"></bean>
<bean id="transaction" class="com.kelly.spring.aop.xml.transaction.Transaction"></bean>
<aop:config>
<!--
切入点表达式 确定目标类
-->
<aop:pointcut
expression="execution(* com.kelly.spring.aop.xml.transaction.PersonDaoImpl.*(..))"
id="perform"/>
<!--
ref指向的对象就是切面
-->
<aop:aspect ref="transaction">
<!--
前置通知
1、在目标方法执行之前
2、获取不到目标方法的返回值
-->
<aop:before method="beginTransaction" pointcut-ref="perform"/>
<!--
后置通知
1、后置通知可以获取到目标方法的返回值
2、当目标方法抛出异常,后置通知将不再执行
-->
<!--
<aop:after-returning method="commit" pointcut-ref="perform" returning="val"/>
-->
<!--
最终通知
无论目标方法是否抛出异常都将执行
-->
<aop:after method="finallyMethod" pointcut-ref="perform"/>
<!--
异常通知
-->
<aop:after-throwing method="throwingMethod" throwing="ex" pointcut-ref="perform"/>
<!--
环绕通知
能控制目标方法的执行
前置通知和后置通知能在目标方法的前面和后面加一些代码,但是不能控制目标方法的执行
-->
<aop:around method="aroundMethod" pointcut-ref="perform"/>
</aop:aspect>
</aop:config>
</beans>
客户端调用 : TransactionTest.java
public class TransactionTest {
@Test
public void testTransaction(){
ApplicationContext context =
new ClassPathXmlApplicationContext("applicationContext.xml");
PersonDao personDao = (PersonDao)context.getBean("personDao");
personDao.savePerson();
}
}