一、AOP原理
1.1 AOP概念
- AOP:面向切面(方面)编程,扩展功能时,不需要修改源代码,只需要修改配置文件就可以了;
- AOP:采取横向抽取机制,取代了传统的纵向继承体系重复性代码;
1.2 AOP原理发展过程
- 纵向抽取机制原理
2. 横向抽取机制:使用动态代理方式实现
1.3 AOP操作术语
- 连接点(join point):类里面哪些方法可以增强,这些方法就称为连接点;
- 切入点(pointcut):在类里面有很多的方法可以被增强,比如实际操作中,只是增强了类里面的某一个方法,则实际增强的方法就称为点。
- 通知/增强(advice):增强的逻辑,称为增强,比如扩展日志功能,,这个日志功能就称为增强。有5种类型的通知:
- 前置通知(Before):在方法被调用之前执行;
- 后置通知(After):在方法被调用之后执行,不管被通知的方法是否执行成功;
- 返回通知(After-Returning):在方法成功执行之后执行;
- 异常通知(After-Throwing):在方法抛出异常后执行;
- 环绕通知(Around):通知包裹了被通知的方法,即在被通知的方法调用之前和之后都执行。
- 切面(Aspect):把增强应用到具体方法上面的过程就称为切面,即把增强用到切入点的过程。
二、AspectJ切面
在Spring里面进行AOP操作,主要使用AspectJ实现
- AspectJ还是Spring一部分,而是和Spring一起使用实现AOP操作;
使用AspectJ实现AOP有两种方法:
- 基于AspectJ的XML配置方式;
- 基于AspectJ的注解方式;
2.1 AOP操作的前期准备
- 除了导入Spring的基本JAR包之外,还需要导入与AOP相关的JAR包;
- aopalliance,aspertjweaver,aop,aspects
Jar包下载链接为:
springframework下载链接:
http://download.csdn.net/detail/u014800380/9766304
- 创建Spring核心配置文件,并且导入AOP的约束;
- 使用表达式定义切入点,表达式的格式为:
execution(<访问修饰符>?<返回类型><方法名>(<参数>)<异常>)
2.2 常用的表达式:
- execution(* com.spring.aop.Book.add(..)),定义了一个访问修饰符任意,在com.spring.aop包下Book类add方法的切面;
- execution(* com.spring.aop.Book.*add(..)),定义了访问修饰符任意,在com.spring.aop包下Book类的任选方法的切面;
- execution(* .(..)),定义了访问修饰符任意,在任意包下任意类任意方法的切面;
- execution(* save.*(..)),定义了所有save开头的方法的切面;
2.3 AOP操作实例(使用XML进行配置)
2.3.1 创建被增强类和增强类
被增强类Book
package com.spring.aop;
public class Book {
public void add(){
System.out.println("book add...");
}
}
增强类BookService
package com.spring.aop;
public class BookService {
public void before(){
System.out.println("bookService add....");
}
}
2.3.2 创建aopBean.xml配置文件,并添加AOP约束
<?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"> <!-- bean definitions here -->
</bean>
2.3.3 在XML配置文件中装配bean和AOP
其中切入点为Book类中的任意方法,切入点id=”pointcut1”;切面为BookService类中的before方法。
<!-- 第一步 配置对象 -->
<bean id="book" class="com.spring.aop.Book"></bean>
<bean id="bookService" class="com.spring.aop.BookService"></bean>
<!-- 第二步 配置AOP操作 -->
<aop:config>
<!-- 2.1 配置切入点 -->
<aop:pointcut expression="execution(* com.spring.aop.Book.*(..))" id="pointcut1"/>
<!-- 2.2 配置切面:把通知用到方法上 -->
<aop:aspect ref="bookService">
<!-- 配置增强类型
method:增强类里面使用哪个方法作为前置 -->
<aop:before method="before" pointcut-ref="pointcut1"/>
</aop:aspect>
</aop:config>
2.3.4 写测试代码
public class aopTest {
@Test
public void testBook(){
ApplicationContext context = new ClassPathXmlApplicationContext("aopBean.xml");
Book book = (Book) context.getBean("book");
book.add();
book.print();
}
}
2.3.5 输出结果
bookService add....
book add...
2.4 AOP的其他操作
2.4.1 修改增强类BookService
需要注意的是环绕方法,需要引入一个ProceedingJoinPoint对象!
package com.spring.aop;
import org.aspectj.lang.ProceedingJoinPoint;
public class BookService {
public void before1(){
System.out.println("bookService before....");
}
public void after1(){
System.out.println("bookService after.....");
}
public void around1(ProceedingJoinPoint jp) throws Throwable{
System.out.println("around before..");
//执行被增强的方法
jp.proceed();
System.out.println("around after..");
}
}
2.4.2 修改配置文件aopBean.xml
<!-- 第一步 配置对象 -->
<bean id="book" class="com.spring.aop.Book"></bean>
<bean id="bookService" class="com.spring.aop.BookService"></bean>
<!-- 第二步 配置AOP操作 -->
<aop:config>
<!-- 2.1 配置切入点 -->
<aop:pointcut expression="execution(* com.spring.aop.Book.*(..))" id="pointcut1"/>
<!-- 2.2 配置切面:把通知用到方法上 -->
<aop:aspect ref="bookService">
<!-- 配置增强类型
method:增强类里面使用哪个方法作为前置 -->
<aop:before method="before1" pointcut-ref="pointcut1"/>
<!-- 后置方法 -->
<aop:after method="after1" pointcut-ref="pointcut1"/>
<!-- 环绕通知方法 -->
<aop:around method="around1" pointcut-ref="pointcut1"/>
</aop:aspect>
</aop:config>
2.4.2 测试代码不变,输出结果
bookService before....
around before..
book add...
around after..
bookService after.....