1. 相关概念
1、切面:所有切入点的集合(通俗讲,就是你的一个新功能)
2、切入点:一组符合某种规则的连接点(通俗讲,就是你要插入的地方的规则)
3、连接点:狭义上通俗的讲指的是某个方法
4、通知:在某个连接点上的某种操作,该操作并非连接点中的操作,而是外来的操作。(就是你功能点的代码)
5、引入(Introduction):引入(在AspectJ中被称为inter-type声明)使得一个切面可以定义被通知对象实现给定的接口,并且可以为那些对象提供具体的实现(就是在已有的方法上添加一段代码,增强功能)
2.编写代码
实例1.事务的声明
实例2:日志打印
applicationContext中需要:
beans参数:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
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
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">
切面配置:
<aop:aspectj-autoproxy proxy-target-class="true"/>
<aop:aspectj-autoproxy/>
<bean id="logAspect" class="aop.LogAspect"/>
<aop:config>
<aop:aspect ref="logAspect">
<aop:pointcut id="logPointCut" expression="execution(* dao..*(..))"/>
<aop:around pointcut-ref="logPointCut" method="doLog"/>
</aop:aspect>
</aop:config>
</beans>
相关的类:
public class LogAspect {
public void doLog(ProceedingJoinPoint point){
String methodName = point.getSignature().getName();
System.out.println("当前执行的方法:"+methodName);
}
}
2.表达式的写法
execution: 匹配指定的方法
execution(void perform()) 匹配项目下所有该方法
execution(void first.Singer.perform()) 匹配具体到某个类的该方法
execution(* first.Artist.perform()) 不考虑返回值类型
execution(* first.Artist.perform(..)) 不考虑返回值类型和参数列表
execution(* first.Aritst.perform(*,*)) 参数必须是两个
execution(* first.Artist.perform(..,java.lang.String))
execution(* find*(..)) 所有方法名符合findXxx 的方法
execution(* com.tarena.service.StoreService.*(..)) 该类中所有方法
execution(* com.tarena.service.*.*(..)) 该包中所有类的所有方法
execution(* com.tarena..*.*(..)) 该包及其子包中所有类的所有方法
通知的可选参数:
任何通知方法可以将第一个参数定义为 org.aspectj.lang.JoinPoint 类型 (环绕通知需要定义为 ProceedingJoinPoint 类型的, 它是 JoinPoint 的一个子类。) JoinPoint 接口提供了一系列有用的方法, 比如 getArgs()(返回方法参数)、getThis()(返回代理对象)、getTarget()(返回目标)、getSignature()(返回正在被通知的方法相关信息)和 toString()(打印出正在被通知的方法的有用信息)。
配置其他类型通知:
- <aop:before method="busiLog" pointcut="execution(* javacommon.base.*Dao.*(..))" />
- <aop:after-throwing throwing="ex" method="afterThrowing" pointcut="execution(* *(..))" />
<aop:pointcut id="logPointCut" expression="execution(* dao..*(..))"/>
<aop:before method="doBeforeLog" pointcut-ref="logPointCut"/>
<aop:after method="doAfterLog" pointcut-ref="logPointCut"/>
同时也可以传递参数:
<aop:before pointcut-ref="performance" method="parameterExecute" arg-names="parameter" />
通知类型:
aop:before
aop:around :环绕:环绕通知在一个方法执行之前和之后执行。(注意有了下面的则不会执行)
aop:after:不论一个方法是如何结束的,在它结束后(finally)后通知(After (finally) advice)都会运行
<aop:after-returning/>返回后通知通常在一个匹配的方法返回的时候执行
<aop:after-throwing> 抛出后通知在一个方法抛出异常后执行
ProceedingJoinPoint is only supported for around advice
报错: Cannot proxy target class because CGLIB2 is not available.
解决:缺少包
导入:
asm 以及aspectjre.jar aspectjweaver.jar 包
报错:0 formal unbound in pointcut
可能参数错误,可能版本不对。
总结:
AOP配置元素 | 功能 |
---|---|
<aop:advisor> | 定义一个AOP通知器 |
<aop:after> | 定义一个AOP后置通知(不考虑被通知的方法是否执行成功) |
<aop:after-returning> | 定义一个AOP返回后通知 |
<aop:after-throwing> | 定义一个AOP抛出后通知 |
<aop:around> | 定义一个AOP环绕通知 |
<aop:aspect> | 定义一个切面 |
<aop:before> | 定义一个AOP前置通知 |
<aop:config> | 顶层的AOP元素。大多数<aop:*>元素必须包含在<aop:config>里 |
<aop:pointcut> | 定义一个切点 |
<aop:declare-parents> | 为被通知的对象引入额外的接口,并透明地实现 |