一、AOP相关概念及原理
1、发展过程
假设对于一个存在的类Student,对其进行功能扩展:
- 传统方式:直接在源码中修改;麻烦易错,不好维护
- 纵向抽取机制扩展:如写一个扩展类,在该类中写扩展方法,让Student基础该类,调用该类的扩展方法;耦合度仍然过高,当父类改变时,仍需要调整Student中的调用形式(如方法名改变、参数改变等)
- 横向抽取机制扩展:及面向切面的思想(AOP),采用动态代理的原理实现。
- 情况一:Studnent实现了某个接口,创建一个与Student**同级**的实现该接口的代理对象进行扩展,及JDK动态代理
- 情况二:Student没有实现接口,则创建Student子类的代理对象,在子类中调用super(父类)中的方法,完成加强,即cglib动态代理
2、相关概念
- 连接点(JoinPoint):可被增强的方法
- 切入点(PointCut):实际增强的方法
通知/增强(Advice):实际增强的功能
- 前置通知:在方法之前增强
- 后置通知:在方法之后增强
- 异常通知:方法出现异常后增强
- 最终通知:在后置之后通知
- 环绕通知:增强的方法要加(ProceedingJoinPoint pjp)形参,调用pjp.proceed();即调用带增强的方法
切面:把增强应用到切入点的过程
二、Spring与Aspectj进行AOP操作(xml配置方式)
1、引入aop的jar包 aopalliance、aspectjweaver、spring-aop、spring-aspects
2、加约束
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
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/context http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
</Beans>
3、创建Student类及切入点的类StudentAdd
public class Student {
public void Show() {
System.out.println("原始:我是一个小学生...");
}
}
public class StudentAdd {
//前置增强
public void ShowBefore() {
System.out.println("前置:我的名字叫小明...");
}
//后置增强
public void ShowAfter() {
System.out.println("后置:我上二年级....");
}
//最终增强
public void ShowFinal() {
System.out.println("最终:我要好好学习...");
}
//环绕增强
public void ShowAro(ProceedingJoinPoint pj) throws Throwable {
System.out.println("前环绕:============");
pj.proceed(); //执行方法
System.out.println("后环绕:************");
}
}
4、Aspectj配置AOP操作
<!-- 扫描包下的所有注解 -->
<context:component-scan base-package="com.aoptest"></context:component-scan>
<!-- 配置对象的创建 -->
<bean id="student" class="com.aoptest.test1.Student"></bean>
<bean id="add" class="com.aoptest.test1.StudentAdd"></bean>
<!-- aop配置 -->
<aop:config>
<!-- 配置切入点(那些方法要增强) -->
<aop:pointcut expression="execution(* com.aoptest.test1.Student.Show(..))" id="show"/>
<!-- 切面配置(将增强应用到上面的方法) -->
<aop:aspect ref="add">
<aop:before method="ShowBefore" pointcut-ref="show"/>
<aop:after method="ShowAfter" pointcut-ref="show"/>
<aop:after-returning method="ShowFinal" pointcut-ref="show"/>
<aop:around method="ShowAro" pointcut-ref="show"/>
</aop:aspect>
</aop:config>