一、SpringAOP主要用于日志,权限控制和事务管理中,在做事务时用得更多。
二、SpringAOP的一些概念:
- SpringAOP被称为面向切面编程;
- Joinpoint连接点:在Spring里面它实际就是我们拦截到的方法
- Pointcut切入点:在Spring里它实际上就是我们所要拦截的方法的定义;
- Advice通知:它是我们在连接点也就是拦截到的方法执行前,执行过程中,以及执行后所要做的处理,这些处理被称为通知,它分为前置通知(在方法执行前被执行的处理),后置通知(在方法成功执行后被执行的处理),最终通知(无论方法是否成功执行,都会执行的处理),例外通知(方法执行期间出现异常会被挂靠的处理);
- Target目标对象:它是代理的委托对象;
三、实现SpringAOP还需要引入以下的包:aspectjweaver.jar,aspectjrt.jar,cglib-nodep-2.1_3.jar,基于注解来实现还需要引用common-annotations.jar这个包。
四、实现SpringAOP功能要修改原来的XML文件,引入AOP命名空间:
<?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-2.5.xsd
http://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context-2.5.xsd
http://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop-2.5.xsd">
<aop:aspectj-autoproxy/>
</beans>
红色部分为我们引入的AOP命名空间,这是必须的。
五、建立切面
- package cn.itcast.service;
- 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;
- /**
- * 切面
- *
- */
- @Aspect
- public class MyInterceptor {
- @Pointcut("execution (* cn.itcast.service.impl.PersonServiceBean.*(..))")//切面表达式,指定要拦截的方法
- private void anyMethod() {}//声明一个切入点,注意它是以方法的形式进行声明的
- @Before("anyMethod() && args(name)")//前置通知,在方法执行前被调用
- public void doAccessCheck(String name) {
- System.out.println("前置通知:"+ name);
- }
- @AfterReturning(pointcut="anyMethod()",returning="result")//后置通知,在方法成功执行后被执行
- public void doAfterReturning(String result) {
- System.out.println("后置通知:"+ result);
- }
- @After("anyMethod()")//最终通知,无论方法是否执行成功都会被执行
- public void doAfter() {
- System.out.println("最终通知");
- }
- @AfterThrowing(pointcut="anyMethod()",throwing="e")//例外通知,在方法抛出异常时才会被执行
- public void doAfterThrowing(Exception e) {
- System.out.println("例外通知:"+ e);
- }
- @Around("anyMethod()")//环绕通知,可能替代上面的所有通知
- public Object doBasicProfiling(ProceedingJoinPoint pjp) throws Throwable {
- //if(){//判断用户是否在权限
- System.out.println("进入方法");
- Object result = pjp.proceed();//要执行这个方法,拦截到的方法才会被执行
- System.out.println("退出方法");
- //}
- return result;
- }
- }
package cn.itcast.service;
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;
/**
* 切面
*
*/
@Aspect
public class MyInterceptor {
@Pointcut("execution (* cn.itcast.service.impl.PersonServiceBean.*(..))")//切面表达式,指定要拦截的方法
private void anyMethod() {}//声明一个切入点,注意它是以方法的形式进行声明的
@Before("anyMethod() && args(name)")//前置通知,在方法执行前被调用
public void doAccessCheck(String name) {
System.out.println("前置通知:"+ name);
}
@AfterReturning(pointcut="anyMethod()",returning="result")//后置通知,在方法成功执行后被执行
public void doAfterReturning(String result) {
System.out.println("后置通知:"+ result);
}
@After("anyMethod()")//最终通知,无论方法是否执行成功都会被执行
public void doAfter() {
System.out.println("最终通知");
}
@AfterThrowing(pointcut="anyMethod()",throwing="e")//例外通知,在方法抛出异常时才会被执行
public void doAfterThrowing(Exception e) {
System.out.println("例外通知:"+ e);
}
@Around("anyMethod()")//环绕通知,可能替代上面的所有通知
public Object doBasicProfiling(ProceedingJoinPoint pjp) throws Throwable {
//if(){//判断用户是否在权限
System.out.println("进入方法");
Object result = pjp.proceed();//要执行这个方法,拦截到的方法才会被执行
System.out.println("退出方法");
//}
return result;
}
}
注意:每一种通知都可以在后面用&&号继续加入拦截条件,例如在上面的例子中在前置通知里面加入了args参数,指定拦截的方法要有一个参数,并且这个参数的值传给了name。在后置通知里面加入了returnning条件,指定方法返回值传给return参数等等。另外要注意的是:这个切面类要交给Spring进行管理,才能实现方法拦截。