在Spring中面向切面编程有两种方式,分别是通过注解的方式和通过xml的方式,以下案例是在Spring3.x版本进行讲解。
一、execution函数
1.1、语法
execution(<访问修饰符>?<方法的返回值类型><方法名>(<参数列表>)<异常>)
1.2、规则
规则 | 表达式 | 示例 |
匹配所有类的public方法 | execution(public **(..)) | |
匹配指定包下所有类的方法(不包含子包) | execution(* 包名.*(..)) | execution(* test.aop.t1.*(..)) |
匹配指定包下所有类的方法(包含子包) | execution(* 包名.**(..)) | execution(* test.aop.t1..*(..)) |
匹配指定类下的所有方法 | execution(* 包名.类名.*(..)) | execution(* test.aop.t1.UserDao.*(..)) |
匹配指定类下的指定方法 | execution(* 包名.类名.方法名(..)) | execution(* test.aop.t1.UserDao.add(..)) |
匹配实现指定接口的所有类的方法 | execution(* 包名.接口名+*(..)) | execution(* test.aop.t1.UserDao+*(..)) |
匹配所有名称以save开头的方法 | execution(* save*(..)) |
二、使用注解的方式实现AOP
2.1、导入Spring的类库
2.2、创建业务功能类UserDao
package test.aop.t1;
public class UserDao {
public void add() {
System.out.println("添加用户");
}
public int update() {
System.out.println("修改用户");
return 1;
}
public void find() {
System.out.println("查询用户");
// System.out.println(10/0); //制造异常
}
}
2.3、创建切面类
package test.aop.t1;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
/**
* 切面类:就是切点与增强的结合
*
* @author thinkpad
*
*/
@Aspect
public class MyAspect {
/**
* 前置通知
*/
@Before(value = "execution(* test.aop.t1.UserDao.add(..))")
public void before() {
System.out.println("前置增强...");
}
/**
* 后置通知,可以获得方法的返回值
*/
@AfterReturning(returning = "returnVal", value = "execution(* test.aop.t1.UserDao.update(..))")
public void afterReturning(Object returnVal){
System.out.println("后置增强...方法的返回值" + returnVal);
}
/**
* 环绕通知,可以阻止目标方法执行
* @return
* @throws Throwable
*/
@Around(value = "MyAspect.myPointcut()")
public Object around(ProceedingJoinPoint joinPoint) throws Throwable{
System.out.println("环绕前增强...");
Object obj = joinPoint.proceed(); //代表目标方法执行
System.out.println("环绕后增强...");
return obj;
}
/**
* 抛出异常通知
*/
@AfterThrowing(throwing="e", value = "MyAspect.myPointcut()")
public void afterThrowing(Throwable e){
System.out.println("不好了,出异常了....,异常信息:"+e.getMessage());
}
/**
* 最终通知,不管是否异常,该通知都会执行
*/
@After(value = "MyAspect.myPointcut()")
public void after(){
System.out.println("总会执行");
}
/**
* 定义切点,目的是定义通用的execution表达式
*/
@Pointcut(value = "execution(* test.aop.t1.UserDao.find(..))")
private void myPointcut() {
}
}
2.4、配置切面
在applicationContext.xml中配置切面生成自动代理
<?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: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/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
<!-- 自动生成代理 -->
<aop:aspectj-autoproxy/>
<bean id="myAspect" class="test.aop.t1.MyAspect"/>
<bean id="userDao" class="test.aop.t1.UserDao"/>
</beans>
2.5、测试
package test.aop.t1;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class JTest {
@Test
public void test() {
ApplicationContext cxt = new ClassPathXmlApplicationContext("applicationContext.xml");
UserDao dao = (UserDao) cxt.getBean("userDao");
// dao.add();
// dao.update();
dao.find();
}
}
2.6、运行结果
三、使用XML的方式实现AOP
3.1、Spring类库
3.2、创建业务功能类UserDao
package test.aop;
public class UserDao {
public void add() {
System.out.println("添加用户");
}
public int update() {
System.out.println("修改用户");
return 1;
}
public void find() {
System.out.println("查询用户");
// System.out.println(10/0); //制造异常
}
}
3.3、创建切面类
package test.aop;
import org.aspectj.lang.ProceedingJoinPoint;
/**
* 切面类:就是切点与增强的结合
*
* @author thinkpad
*
*/
public class MyAspect {
/**
* 前置通知
*/
public void before() {
System.out.println("前置增强...");
}
/**
* 后置通知,可以获得方法的返回值
*/
public void afterReturning(Object returnVal){
System.out.println("后置增强...方法的返回值" + returnVal);
}
/**
* 环绕通知,可以阻止目标方法执行
* @return
* @throws Throwable
*/
public Object around(ProceedingJoinPoint joinPoint) throws Throwable{
System.out.println("环绕前增强...");
Object obj = joinPoint.proceed(); //代表目标方法执行
System.out.println("环绕后增强...");
return obj;
}
/**
* 抛出异常通知
*/
public void afterThrowing(Throwable e){
System.out.println("不好了,出异常了....,异常信息:"+e.getMessage());
}
/**
* 最终通知,不管是否异常,该通知都会执行
*/
public void after(){
System.out.println("总会执行");
}
}
3.4、在applicationContext.xml中配置切面
<?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: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/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
<bean id="userDao" class="test.aop.UserDao"/>
<bean id="myAspect" class="test.aop.MyAspect"/>
<aop:config>
<!-- 定义切点 -->
<aop:pointcut expression="execution(* test.aop.UserDao.add(..))" id="addPointcut"/>
<aop:pointcut expression="execution(* test.aop.UserDao.update(..))" id="updatePointcut"/>
<aop:pointcut expression="execution(* test.aop.UserDao.find(..))" id="findPointcut"/>
<!-- 定义切面 -->
<aop:aspect ref="myAspect">
<aop:before method="before" pointcut-ref="addPointcut"/>
<aop:after-returning method="afterReturning" returning="returnVal" pointcut-ref="updatePointcut"/>
<aop:around method="around" pointcut-ref="findPointcut"/>
<aop:after-throwing method="afterThrowing" throwing="e" pointcut-ref="findPointcut"/>
<aop:after method="after" pointcut-ref="findPointcut"/>
</aop:aspect>
</aop:config>
</beans>
3.5、测试
package test.aop;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class JTest {
@Test
public void test() {
ApplicationContext cxt = new ClassPathXmlApplicationContext("applicationContext.xml");
UserDao dao = (UserDao) cxt.getBean("userDao");
// dao.add();
// dao.update();
dao.find();
}
}
3.6、运行结果
四、源代码