AOP 术语
- 通知: 就是增强的方法(如记录日志,事务等)
- 连接点:就是指Spring允许你增强的地方都可以称为连接点,Spring支持方法连接点,所以方法的前后都可以是连接点。
- 切入点: 就是在连击点的基础上,来定义切入点。不想把通知运用到所有的方法上,就可以定义切入点。
- 切面就是通知+切入点。
通知类型:
1> @Before: 前置通知,在方法执行前执行
2> @After: 后置通知,在方法执行后执行
3>@AfterReturning: 返回通知,在方法返回结果后执行。
4>@AfterThrowing:异常通知,在方法抛出异常后执行
5>@Around: 环绕通知,围绕着方法执行。
基于注解的AOP实现
-
定义一个切面:
定义一个类,用 @Component 将该类交给容器管理
使用@Aspect 注解来申明该类是 一个切面 -
在 通知方法 上申明通知类型,如 @Before
-
通过切入点表达式定义切点
@Before(value = "execution(*
com.test.spring.aop.dao.ArithmeticCalculator.*(..))") -
启用Aspect 注解,让Spring 自动创建代理对象
<aop:aspectj-autoproxy />
切入点表达式详解:
- 只有执行ArithmeticCalculator中的add方法时才会执行通知
execution(public int cn.xiechengxu.spring.aop.dao.ArithmeticCalculator.add(int,
int))*
-
只有执行ArithmeticCalculator中的所有方法时才会执行通知
execution(public int cn.xiechengxu.spring.aop.dao.ArithmeticCalculator.*(int, int))
-
只有执行ArithmeticCalculator中的所有方法时才会执行通知而且不考虑权限修饰符和返回值类型
execution(*
cn.xiechengxu.spring.aop.dao.ArithmeticCalculator.*(int, int)) -
只有执行ArithmeticCalculator中的所有方法时才会执行通知而且不考虑权限修饰符和返回值类型以及参数的类型和个数
execution(*
com.atguigu.spring.aop.dao.ArithmeticCalculator.*(..))
- 执行所有类中的所有方法时都会执行通知而且不考虑权限修饰符和返回值类型以及参数的类型和个数
execution(* .(..))
在定义通知方法时,可以传入JoinPoint 参数,
// 获取方法名
String methodName = jp.getSignature().getName();
// 获取参数
Object[] args = jp.getArgs();
在返回类型的通知上,可以指定返回值。
@AfterReturning(pointcut = "execution(*
cn.xiechengxu.spring.aop.dao.ArithmeticCalculator.*(..))",
returning = "result")
定义环绕通知时,传入ProceedingJoinPoint 类型的参数
可以把切入点表达式单独提出来:
@Pointcut(value="execution(*
cn.xiechengxu.spring.aop.dao.ArithmeticCalculator.*(..))")
public void pointCut(){
};
@Around("pointCut()")
public Object aroundLogging(ProceedingJoinPoint pjp) { }
//获取方法名
String methodName = pjp.getSignature().getName();
//获取参数
Object[] args = pjp.getArgs();
执行方法:
result = pjp.proceed();
切面的优先级
通过@Order 注解指定切面优先级,value 值越小,优先级越高。 默认值是Integer 的最大值。
@Order(100)
基于Xml 实现AOP
- 在xml中配置切面bean
- 使用 <aop: config> 标签
- 在标签中配置切点
- 配置切面
<!-- 配置切面bean -->
<bean id="loggingAspect"
class="cn.xiechengxu.spring.xml.LoggingAspect"></bean>
<!-- 配置AOP -->
<aop:config>
<!-- 配置切入点表达式 -->
<aop:pointcut expression="execution(*
com.atguigu.spring.xml.ArithmeticCalculator.*(..))" id="pointCut"/>
<!-- 配置切面 -->
<aop:aspect ref="loggingAspect">
<!-- 配置前置通知 -->
<aop:before method="beforeLogging"
pointcut-ref="pointCut"/>
<!-- 配置后置通知 -->
<aop:after method="AfterLogging"
pointcut-ref="pointCut"/>
<!-- 配置返回通知 -->
<aop:after-returning method="returnLogging"
pointcut-ref="pointCut" returning="result"/>
<!-- 配置异常通知 -->
<aop:after-throwing method="throwLogging"
pointcut-ref="pointCut" throwing="e"/>
<!-- 配置环绕通知 -->
<aop:around method="aroundLogging"
pointcut-ref="pointCut"/>
</aop:aspect>
</aop:config>
网友评论