1 概述
1.1 aspectj
1 在spring里面进行aop操作,使用aspectj实现
(1)aspectj不是spring一部分,和spring一起使用进行aop操作
(2)Spring2.0以后新增了对AspectJ支持
1.2 两种方式
2 使用aspectj实现aop有两种方式(重点)
(1)基于aspectj的xml配置
(2)基于aspectj的注解方式
2 Aop操作准备—aspect
2.1 导包
1 除了导入基本的jar包之外,还需要导入aop相关的jar包
2.2 引入约束
2 创建spring核心配置文件,导入aop的约束
3 增强类
被加强的方法所在的类叫被增强类
3.1 切入点表达式
1 切入点:实际增强的方法
2 常用的表达式
execution(<访问修饰符>?<返回类型><方法名>(<参数>)<异常>)
(1)execution(* spring.aop.Book.add(..))
(2)execution(* spring.aop.Book.*(..))
(3)execution(* *.*(..))
(4) 匹配所有save开头的方法 execution(* save*(..))
3. 切入点表达式操作符 &&, ||, !
在 AspectJ 切面中, 可以通过 @Pointcut 注解将一个切入点声明成简单的方法. 切入点的方法体通常是空的。
3.2 五种通知
3.2.1 前置通知-- JoinPoint访问连接点
前置通知:在方法执行之前执行的通知; 前置通知使用 @Before 注解, 并将切入点表达式的值作为注解值.
可以在通知方法中声明一个类型为 JoinPoint 的参数. 然后就能访问链接细节. 如方法名称和参数值.
//声明该方法是一个前置通知:在目标方法开始前执行
@Before("execution(publicint spring.aop.impl.*.*(int , int))")
public void beforeMethod(JoinPoint joinPoint){
String methodName = joinPoint.getSignature().getName();
List<Object> args = Arrays.asList(joinPoint.getArgs());
System.out.println("此方法 "+ methodName +" 开始:" + args);
}
3.2.2 后置通知-- JoinPoint
后置通知是在连接点完成之后执行的, 即连接点返回结果或者抛出异常的时候, 下面的后置通知记录了方法的终止.
一个切面可以包括一个或者多个通知.
//后置通知:在目标方法开始后执行(无论是否发生异常),其不能访问控制结果
@After("execution(publicint spring.aop.impl.*.*(int , int))")
public void afterMethod(JoinPoint joinPoint){
String methodName = joinPoint.getSignature().getName();
System.out.println("此方法 "+ methodName +" 结束");
}
3.2.3 返回通知—JoinPoint,result访问连接点的返回值
在返回通知中, 只要将 returning 属性添加到 @AfterReturning 注解中, 就可以访问连接点的返回值. 该属性的值即为用来传入返回值的参数名称.
必须在通知方法的签名中添加一个同名参数. 在运行时, Spring AOP 会通过这个参数传递返回值.
原始的切点表达式需要出现在 pointcut 属性中
//返回通知:在目标方法开始后执行,是可以访问到方法的返回值的
@AfterReturning(value = "execution(publicint spring.aop.impl.*.*(int , int))" , returning = "result")
public void afterReturning(JoinPoint joinPoint , Object result){
String methodName = joinPoint.getSignature().getName();
System.out.println("此方法 "+ methodName +" 结果: " + result);
}
3.2.4 异常通知—JoinPoint,Exception
只在连接点抛出异常时才执行异常通知
将 throwing 属性添加到 @AfterThrowing 注解中, 也可以访问连接点抛出的异常. Throwable 是所有错误和异常类的超类. 所以在异常通知方法可以捕获到任何错误和异常.
//异常通知:在目标方法异常后执行;是可以访问到 异常对象
@AfterThrowing(value = "execution(publicint spring.aop.impl.*.*(int , int))" ,throwing = "e")
public void afterThrowing(JoinPoint joinPoint , Exception e){
String methodName = joinPoint.getSignature().getName();
System.out.println("此方法 "+ methodName +" 异常: " + e);
}
3.2.5 环绕通知—ProceedingJoinPoint连接点
环绕通知相当于前面四种的一个概括
对于环绕通知来说, 连接点的参数类型必须是 ProceedingJoinPoint ,其中proceed() 方法来执行被代理的方法. 如果忘记这样做就会导致通知被执行了, 但目标方法没有被执行.
注意: 环绕通知的方法需要返回目标方法执行之后的结果, 即调用 joinPoint.proceed(); 的返回值, 否则会出现空指针异常
//把这个类声明为一个对象:需要把该类放入 IOC 容器中,再声明一个切面
@Aspect
@Component
public class Logging {
/**
* 环绕通知:相当于前四种通知的集合
* 需要携带ProceedingJoinPoint 类型参数
* 类似动态代理的全过程,ProceedingJoinPoint类型参数可以决定是否执行目标方法,且要有返回值
*/
@Around("execution(publicint spring.aop.impl.*.*(int , int))")
public Object aroundMethod(ProceedingJoinPoint pjp){
Object result = null;
String methodName = pjp.getSignature().getName();
List<Object> args = Arrays.asList(pjp.getArgs());
try {
//前置通知
System.out.println("前置通知此方法 "+ methodName +" 开始:" + args);
//执行方法
result = pjp.proceed();
//返回通知
System.out.println("返回通知此方法 "+ methodName +" 结果: " + result);
} catch (Throwable e) {
//异常通知
System.out.println("异常通知此方法 "+ methodName +" 异常: " + e);
throw new RuntimeException(e);
}
//后置通知
System.out.println("后置通知此方法 "+ methodName +" 结束");
return result;
}
}
3.3 切面优先级
4 Aspectj的aop操作(xml配置)
4.1 增强类
4.2 XML配置
4.2.1 配置
4.2.2 配置切入点
切入点使用<aop:pointcut> 元素声明
切入点必须定义在 <aop:aspect> 元素下, 或者直接定义在<aop:config> 元素下.
定义在 <aop:aspect> 元素下: 只对当前切面有效
定义在 <aop:config> 元素下: 对所有切面都有效
基于 XML 的 AOP 配置不允许在切入点表达式中用名称引用其他切入点.
4.2.3 配置切面—引入增强对象
当使用 XML 声明切面时, 需要在 <beans> 根元素中导入 aop Schema
在 Bean 配置文件中, 所有的 Spring AOP 配置都必须定义在 <aop:config> 元素内部. 对于每个切面而言, 都要创建一个<aop:aspect> 元素来为具体的切面实现引用后端 Bean 实例.
切面 Bean 必须有一个标示符, 供 <aop:aspect> 元素引用
4.2.4 配置通知—引入切入点
在 aop Schema 中, 每种通知类型都对应一个特定的 XML 元素.
通知元素需要使用 <pointcut-ref> 来引用切入点, 或用 <pointcut> 直接嵌入切入点表达式. method 属性指定切面类中通知方法的名称.
<!-- 1.创建对象 -->
<bean id="book" class="spring.aop.Book"></bean>
<bean id="myBook" class="spring.aop.MyBook"></bean>
<!-- 2.配置aop操作 -->
<aop:config>
<!-- 2.1配置切入点 -->
<aop:pointcut expression="execution(* spring.aop.Book.*(..))"id="pointcut1"/>
<!-- 2.2配置切面 把增强用到方法上面-->
<aop:aspect ref="myBook">
<!-- 配置增强类型 method:增强类里面使用哪个方法作为前置-->
<aop:before method="before1" pointcut-ref="pointcut1"/>
<aop:after-returning method="after1" pointcut-ref="pointcut1"/>
<aop:around method="around1" pointcut-ref="pointcut1"/>
</aop:aspect>
</aop:config>
5 aop操作(注解)
5.1 XML
第一步 创建对象
第二步 在spring核心配置文件中,开启aop操作
5.2 增强类注解
第三步 在增强类上面使用注解完成aop操作