AspectJ:
AspectJ是一个基于Java语言的AOP框架
jar包:
AOP联盟:com.springsource.org.aopalliance-1.0.0.jar
spring aop实现:spring-aop-3.2.0.RELEASE.jar
Aspectj规范:com.springsource.org.aspectj.weaver-1.6.8.RELEASE.jar
spring aspect实现:spring-aspects-3.2.0.RELEASE.jar
切入点表达式:
1.execution() 用于描述方法(用法在spring--aop中有介绍)
2.within() 用于描述包的,匹配包或子包中的方法(了解)
3.this() 用于描述当前对象,匹配实现接口的代理对象中的方法(了解)
4.target() 用于描述目标对象,匹配实现接口的目标类中的方法(了解)
5.args() 用于描述参数,匹配参数格式符合标准的方法(了解)
6.bean() 用于描述指定bean
通知类型:
aspectj通知类型:前置通知、后置通知、环绕通知、异常抛出通知、最终通知
1)before:前置通知(应用:各种校验)
在方法执行前执行,如果通知抛出异常,阻止目标方法运行
2)afterReturning:后置通知(应用:常规数据处理)
方法正常返回后执行,如果目标方法中抛出异常,通知无法执行
必须在方法执行后才执行,所以可以获得方法的返回值。
3)around:环绕通知(应用:十分强大,可以做任何事情)【必须是Object的,必须要有第一个参数,
它的参数是JoinPoint的子接口ProceedingJoinPoint joinPoint,对外必须要抛出异常,
手动执行目标方法joinPoint.proceed()】
方法执行前后分别执行,可以阻止方法的执行
4)afterThrowing:抛出异常通知(应用:包装异常信息、记录日志(info、warn、error)等)
方法抛出异常后执行,如果方法没有抛出异常,无法执行
5)after:最终通知(应用:清理现场)
方法执行完毕后执行,无论方法中是否出现异常
环绕
try{
//前置通知
手动执行目标方法 Object obj = ...
//后置通知
} catch{
//抛出异常通知
} finally{
//最终通知
}
通知演示XML配置:
public class MyAspect {
public void myBefore(JoinPoint joinPoint){
System.out.println("前置通知:" + joinPoint.getSignature().getName());
}
public void myAfterReturning(JoinPoint joinPoint,Object val){
System.out.println("后置通知:" + joinPoint.getSignature().getName() + " @ " + val);
}
public Object myAround(ProceedingJoinPoint joinPoint) throws Throwable{
System.out.println("环绕前");
//手动执行目标方法
Object obj = joinPoint.proceed();
System.out.println("环绕后");
return obj;
}
public void myAfterThrowing(JoinPoint joinPoint, Throwable e){
System.out.println("抛出异常通知" + e.getMessage());
}
public void myAfter(JoinPoint joinPoint){
System.out.println("最终通知");
}
}
<!-- 1 创建service -->
<bean id="userServiceId" class="cn.xxx.d_aspect.a_xml.UserServiceImpl"></bean>
<!-- 2 切面类 -->
<bean id="myAspectId" class="cn.xxx.d_aspect.a_xml.MyAspect"></bean>
<!-- 3 aop aspectj编程
<aop:aspect> 进行aspect配置,切面配置
* ref 用于引用切面类,从而确定通知(方法名)
<aop:pointcut> 声明切入点
-->
<aop:config>
<aop:aspect ref="myAspectId">
<aop:pointcut expression="execution(* cn.xxx.d_aspect.a_xml.*.*(..))" id="myPointcut"/>
<!-- 3.1 前置通知
* 配置:<aop:before method="myBefore" pointcut-ref="myPointcut"/>
* 通知:public void myBefore(JoinPoint joinPoint){
具有一个参数,可以获得当前连接点的描述信息。例如:方法名称 joinPoint.getSignature().getName()
类型:org.aspectj.lang.JoinPoint
<aop:before method="myBefore" pointcut-ref="myPointcut"/>
-->
<!-- 3.2 后置通知 ,在目标方法之后执行,所以可以获得目标方法返回值
* 配置:<aop:after-returning method="myAfterReturning" pointcut-ref="myPointcut" returning="val"/>
* 通知:public void myAfterReturning(JoinPoint joinPoint,Object val){
参数1:当前连接点描述
参数2:返回值,类型必须是Object,参数名称必须是 <aop:after-returning ...returning="
">设置的。
<aop:after-returning method="myAfterReturning" pointcut-ref="myPointcut" returning="val"/>
-->
<!-- 3.3 环绕通知 ,必须手动执行目标方法
* 配置:<aop:around method="myAround" pointcut-ref="myPointcut" />
* 通知:public Object myAround(ProceedingJoinPoint joinPoint) throws Throwable{
1)返回类型必须是Object
2)方法参数必须是ProceedingJoinPoint
3)必须抛出异常Throwable
4)执行目标方法:Object obj = joinPoint.proceed();
<aop:around method="myAround" pointcut-ref="myPointcut" />
-->
<!-- 3.4 抛出异常 ,只有发生异常时,才执行。通常不执行。
* 配置:<aop:after-throwing method="myAfterThrowing" pointcut-ref="myPointcut" throwing="e"/>
* 通知:public void myAfterThrowing(JoinPoint joinPoint, Throwable e){
参数1:。。。
参数2:异常的描述信息,类型必须Throwable,参数名称通过 throwing 配置确定
<aop:after-throwing method="myAfterThrowing" pointcut-ref="myPointcut" throwing="e"/>
-->
<!-- 3.5 最终通知
* 配置: <aop:after method="myAfter" pointcut-ref="myPointcut"/>
* 通知:public void myAfter(JoinPoint joinPoint){
-->
<aop:after method="myAfter" pointcut-ref="myPointcut"/>
</aop:aspect>
</aop:config>
注解配置:
@service声明service层,加注在service的实现层上@service("userService")。
@Component声明不好归类的组件。例如:@Component("myAspectId")
service和component的生效要通过context的扫描才能够生效。
@Aspect 声明切面 @Before 前置 @AfterReturning 后置 @Around 环绕
@AfterThrowing 抛出异常 @After 最终
@Pointcut 声明切入点,修饰固定方法上 private void 自定义(){}
以上注解要生效,必须在xml配置
<aop:aspectj-autoproxy>
前置通知:@Before("execution(* cn.xxx.d_aspect.b_annotation.*.*(..))")
后置通知:@AfterReturning(value="myPointCut()" ,returning="val")
声明切入点,达到表示共享。使用时相当于方法调用
@Pointcut("execution(* cn.xxx.d_aspect.b_annotation.*.*(..))")
private void myPointCut(){}【在切面类中进行声明】
环绕通知:@Around("execution(* cn.xxx.d_aspect.b_annotation.*.*(..))")
抛出异常通知:@AfterThrowing(value="myPointCut()" ,throwing="e")