Aop
1.Aop
中文名称:面向切面编程
英文名称:Aspect Oriented Programming
定义: 在程序原有的纵向执行流程中,针对某一个或某一些方法添加通知形成横向切面的过程,称为Aop.
优点:
1. 高扩展
2. 原有功能可以释放部分功能。(功能更明确)
2.Aop常用概念
- 切点 :原有功能。 pointcut
- 前置通知: 在切点之前执行。 before advice
- 后置通知: 在切点之后执行。 after advice
- 异常通知:在切点出现异常时触发。 throws advice
- 切面 :所有功能的总称。
- 织入 :将切面嵌入到原有功能的过程。
3.Spring实现Aop的几种方式 - 基于Schema-base 方式 (自学)
1.1. 每个通知必须实现接口或类
1.2 在Spring配置文件中的 aop:config标签中配置
2 . 基于AspectJ XML配置方式
1.1. 每个通知不需要实现接口或类。(定义一个通知方法)
1.2 在Spring配置文件中的 aop:config的子标签aop:aspect标签中配置。
3 . 基于AspectJ 注解方式
1.1. 每个通知不需要实现接口或类。(定义一个通知方法)
1.2 使用对应的注解完成aop配置。
4.基于AspectJ XML配置方式实现Aop
4.1. 导入Spring核心容器和Aop的相关jar包
4.2.创建applicationContext.xml配置文件
注意:引入aop的命名空间 aop.xsd
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd">
</beans>
4.3.创建通知类,类中提供相关的通知方法
/**
-
通知类,通知方法
*/
public class MyAdvice {/**
- 前置通知方法
*/
public void mybefore() {
System.out.println(“前置通知…”);
}
public void myafter() {
System.out.println(“后置通知…”);
}public void myaftering(){
System.out.println(“后置通知returing…”);
}
/**- 异常通知方法
/
public void mythrow(Exception e) {
System.out.println(“异常通知…异常信息:”+e);
}
/* - 环绕通知方法=前置通知+后置通知
- @throws Throwable
*/
public Object myaround(ProceedingJoinPoint p) throws Throwable {
//前置通知
System.out.println(“环绕前置通知…”);
//切点方法,放行
Object o=p.proceed();
//后置通知
System.out.println(“环绕后置通知…”);
return o;
}
}
4.4.配置文件配置Aop
- 前置通知方法
<bean id="myadvice" class="advice.MyAdvice"></bean>
<!-- 配置Demo对象 -->
<bean id="demo" class="demo.Demo"></bean>
<!-- 配置AOP -->
<aop:config>
<!-- 切面 -->
<aop:aspect ref="myadvice">
<!-- 切点 -->
<aop:pointcut expression="execution(* demo.Demo.demo2())" id="myPoint"/>
<!-- 前置通知 -->
<aop:before method="mybefore" pointcut-ref="myPoint"/>
<!-- 后置通知 :不管是否出现异常,都执行-->
<aop:after method="myafter" pointcut-ref="myPoint"/>
<!-- 后置通知 :只有切点没有出现异常时,才执行-->
<aop:after-returning method="myaftering" pointcut-ref="myPoint"/>
<!-- 异常通知 :当切点出现异常时 throwing:异常通知方法参数名-->
<aop:after-throwing method="mythrow" pointcut-ref="myPoint" throwing="e"/>
<!-- 环绕通知=前置通知+后置通知 -->
<aop:around method="myaround" pointcut-ref="myPoint"/>
</aop:aspect>
</aop:config>
扩展1:获取切点连接点相关信息,在通知方法上加JoinPoint参数
public void myafter(JoinPoint p) {
System.out.println(“后置通知…”+p.getTarget()+“\t”+
p.getSignature().getName()+“\t”+Arrays.toString(p.getArgs()));
}
public Object myaround(ProceedingJoinPoint p) 环绕通知
扩展2:切点表达式通配符
-
- 匹配任意一个方法,任意一个类,任意一个包。
如:demo.Demo.()
service….*() : …代表当前包以及子包
- 匹配任意一个方法,任意一个类,任意一个包。
-
… 作为方法参数,匹配任意参数
service….(…) -
基于AspectJ 注解配置方式实现Aop
-
- 相关注解
@Component 等价于,将类交给Spring管理
@Aspect 等价于aop:aspect。切面注解,代表通知切点类。
@PointCut 切点注解
@Before 前置通知注解
@After 后置通知注解
@AfterReturning 后置通知注解
@AfterThrowing 异常通知注解
@Around 环绕通知注解
6.2:通过注解修改Aop相关通知类
@Component
public class Demo {
}
@Component
@Aspect
public class MyAdvice {
//切点方法
@Pointcut(“execution(* demo.Demo.*(…))”)
public void pointcut() {
}
- 相关注解
/**
* 前置通知方法
*/
@Before("pointcut()")
public void mybefore() {
System.out.println("前置通知....");
}
@After("pointcut()")
public void myafter(JoinPoint p) {
System.out.println("后置通知...."+p.getTarget()+"\t"+
p.getSignature().getName()+"\t"+Arrays.toString(p.getArgs()));
}
@AfterReturning("pointcut()")
public void myaftering(){
System.out.println("后置通知returing....");
}
/**
* 异常通知方法
*/
@AfterThrowing("pointcut()")
public void mythrow(Exception e) {
System.out.println("异常通知....异常信息:"+e);
}
/**
* 环绕通知方法=前置通知+后置通知
* @throws Throwable
*/
@Around("pointcut()")
public Object myaround(ProceedingJoinPoint p) throws Throwable {
}
}
6.3:配置文件中配置Spring扫描注解
注意: 默认Spring不扫描注解。开启自动扫描注解。
引入context 命名空间。
<context:component-scan base-package=“demo,advice”></context:component-scan>
<!-- 设置动态代理为 cglib动态代理 ,默认是false:jdk动态代理-->
<aop:aspectj-autoproxy proxy-target-class="true"></aop:aspectj-autoproxy>