1、 AsbectJ切入点表达式
1. 再配置切入点的时候,需要定义表达式,重点的格式如下:execution(public * *(..)),具体展开如下:
* 切入点表达式的格式如下:
* execution([修饰符] 返回值类型 包名.类名.方法名(参数))
* 修饰符可以省略不写,不是必须要出现的。
* 返回值类型是不能省略不写的,根据你的方法来编写返回值。可以使用 * 代替。
* 包名例如:com.spring.demo3.BookDaoImpl
* 首先com是不能省略不写的,但是可以使用 * 代替
* 中间的包名可以使用 * 号代替
* 如果想省略中间的包名可以使用 ..
* 类名也可以使用 * 号代替,也有类似的写法:*DaoImpl
* 方法也可以使用 * 号代替
* 参数如果是一个参数可以使用 * 号代替,如果想代表任意参数使用 ..
2. 代码如下
<!-- 配置AOP-->
<aop:config>
<!-- 先配置切面:通知+切入点 -->
<aop:aspectref="logAspect">
<!-- 配置通知的类型,配置切入点 -->
<!-- 切入点的表达式
execution() 固定的
1. public可以省略不写的
2. void代表返回值类型,不能省略的,编写其他的值
3. 可以使用*号代替的 *..*表示任意包
4. 类名尽量不要直接使用 * ,使用*DaoImpl
5. 方法:save*
6. 参数列表中编写了*,代表方法中只有一个参数,如果表示任意的参数,可以编写 ..
-->
<!-- <aop:beforemethod="writeLog" pointcut="execution(public void cn.itcast.demo4.BookDaoImpl.save())"/>-->
<!-- <aop:beforemethod="writeLog" pointcut="execution(*cn.itcast.demo4.BookDaoImpl.save())"/> -->
<!-- <aop:beforemethod="writeLog" pointcut="execution(*cn.*.*.BookDaoImpl.save())"/> -->
<!-- <aop:beforemethod="writeLog" pointcut="execution(*cn.*.*.*DaoImpl.save*())"/> -->
<aop:beforemethod="writeLog" pointcut="execution(*cn.*.*.*DaoImpl.save*(..))"/>
</aop:aspect>
</aop:config>
2、 配置通用切入点
1. 如果有多个切入点,那么在aop的配置中需要配置多个切入点,那么再维护的时候会比较麻烦,所以可以把切入点配置成通用的,使用引用的格式。
2. 可以把<aop:pointcut>配置在<aop:aspect>标签下
<!-- 配置AOP-->
<aop:config>
<!-- 先配置切面:通知+切入点 -->
<aop:aspectref="logAspect">
<!-- 配置通用的切入点 -->
<aop:pointcut expression="execution(*cn.*.*.*DaoImpl.save(..))" id="pt"/>
<aop:beforemethod="writeLog" pointcut-ref="pt"/>
<!-- save方法之前开启事务 -->
<aop:beforemethod="beginTransaction" pointcut-ref="pt"/>
</aop:aspect>
</aop:config>
3. 可以把<aop:pointcut>配置到<aop:config>标签下
<!-- 配置AOP-->
<aop:config>
<!-- 配置通用的切入点 -->
<aop:pointcutexpression="execution(* cn.*.*.*DaoImpl.save(..))"id="pt"/>
<!-- 先配置切面:通知+切入点 -->
<aop:aspectref="logAspect">
<aop:beforemethod="writeLog" pointcut-ref="pt"/>
<!-- save方法之前开启事务 -->
<aop:beforemethod="beginTransaction" pointcut-ref="pt"/>
</aop:aspect>
</aop:config>
3、 AOP的通知类型
a. 前置通知
* 在目标类的方法执行之前执行。
* 配置文件信息:<aop:aftermethod="before" pointcut-ref="myPointcut3"/>
* 应用:可以对方法的参数来做校验
b. 最终通知
* 在目标类的方法执行之后执行,如果程序出现了异常,最终通知也会执行。
* 在配置文件中编写具体的配置:<aop:aftermethod="after" pointcut-ref="myPointcut3"/>
* 应用:例如像释放资源
c. 后置通知
* 方法正常执行后的通知。
* 在配置文件中编写具体的配置:<aop:after-returningmethod="afterReturning" pointcut-ref="myPointcut2"/>
* 应用:可以修改方法的返回值
d. 异常抛出通知
* 在抛出异常后通知
* 在配置文件中编写具体的配置:<aop:after-throwingmethod="afterThorwing" pointcut-ref="myPointcut3"/>
* 应用:包装异常的信息
e. 环绕通知
* 方法的执行前后执行。
* 在配置文件中编写具体的配置:<aop:aroundmethod="around" pointcut-ref="myPointcut2"/>
* 要注意:目标的方法默认不执行,需要使用ProceedingJoinPoint对来让目标对象的方法执行。
4、 在通知中获取参数
a. 编写了通知的方法,那么在通知的方法中存在参数,第一个参数是Joinpoint(连接点)
* 例如:
public void before(JoinPoint jp){
Object [] objs = jp.getArgs();
System.out.println(objs.length);
System.out.println("before...");
}
* 注意:JoinPoint参数必须要放在第一个位置。
b. 第二个参数是:ProceedingJoinPoint,该对象是JoinPoint的子类,所以ProceedingJoinPoint接口也可以获取参数
c. 获取方法值执行的返回值
* around环绕通知获取到返回值:Objectobj = pjp.proceed(pjp.getArgs());获取返回值
* afterReturning获取返回值
* 需要在配置文件中配置:<aop:after-returningmethod="afterReturning" pointcut-ref="pt"returning="abc"/>
* 在public voidafterReturning(Object abc){}定义参数,abc的名称必须要相同,abc就是返回值