一、AOP简介及核心概念
AOP(Aspect Oriented Programming)面向切面编程,一种编程范式,指导开发者如何组织程序结构,跟OOP(Object Oriented Programming)面向对象编程也是一样,也是一种编程思想。
作用:在不惊动原始设计的基础上为其进行功能增强
Spring理念:无入侵式/无侵入式
● 连接点(JoinPoint):程序执行过程中的任意位置,粒度为执行方法,抛出异常,设置变量等
■ 在SpringAOP,理解为方法的执行
● 切入点(Pointcut):匹配连接点的式子
■ 在SpringAOP中,一个切入点可以只描述一个具体方法,也可以匹配多个方法
◆ 一个具体方法,com.itheima.dao包下的BookDao接口中的无形参无返回值的save方法
◆ 匹配多个方法:所有的save方法,所有的get开头的方法,所有以Dao结尾的接口中的任意方法,所有带有一个参数的方法
● 通知(Advice):在切入点处执行的操作,也就是共性功能
■ 在SpringAOP中,功能最终以方法的形式呈现
● 通知类:定义通知的类
● 切面(Aspect):描述通知与切入点的对应关系
二、AOP入门案例(注解版)
案例设定:测定接口执行效率
简化设定:在接口执行前输出当前系统时间
开发模式:XML or 注解
思路分析:
1、导入坐标(pom.xml)
<dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>1.9.4</version> </dependency>
说明:spring-context坐标默认依赖spring-aop坐标
2、定义dao接口与实现类
public interface BookDao { public void save(); public void update(); }
@Repository public class BookDaoImpl implements BookDao { public void save() { System.out.println(System.currentTimeMillis()); System.out.println("book dao save ..."); } public void update(){ System.out.println("book dao update ..."); } }
3、定义通知类、制作通知
public class MyAdvice { public void before(){ System.out.println(System.currentTimeMillis()); } }
4、定义切入点
public class MyAdvice { //设置切入点,要求配置在方法上方 @Pointcut("execution(void com.itheima.dao.BookDao.update())") private void pt(){} }
说明:切入点定义依托一个不具有实际意义的方法进行,即无参数,无返回值,方法体无实际逻辑
5、绑定切入点与通知关系,并指定通知添加到原始连接点的具体执行位置
public class MyAdvice { //设置切入点,要求配置在方法上方 @Pointcut("execution(void com.itheima.dao.BookDao.update())") private void pt(){} //设置在切入点pt()的前面运行当前操作(前置通知) @Before("pt()") public void before(){ System.out.println(System.currentTimeMillis()); } }
6、定义通知类受Spring容器管理,并定义当前类为切面类
//通知类必须配置成Spring管理的bean @Component //设置当前类为切面类类 @Aspect public class MyAdvice { //设置切入点,要求配置在方法上方 @Pointcut("execution(void com.itheima.dao.BookDao.update())") private void pt(){} //设置在切入点pt()的前面运行当前操作(前置通知) // @Before("pt()") public void method(){ System.out.println(System.currentTimeMillis()); } }
7、开启Spring对AOP注解驱动支持
@Configuration @ComponentScan("com.itheima") //开启注解开发AOP功能 @EnableAspectJAutoProxy public class SpringConfig { }
自此入门案例结束。
三、AOP工作流程
1、Spring容器启动
2、读取所有切面配置中的切入点
@Component @Aspect public class MyAdvice { @Pointcut("execution(void com.itheima.dao.BookDao.save())") private void ptx(){} @Pointcut("execution(void com.itheima.dao.BookDao.update())") private void pt(){} @Before("pt()") public void method(){ System.out.println(System.currentTimeMillis()); } }
3、初始化bean,判定bean对应的类中的方法是否匹配到任意切入点
● 匹配失败,创建对象
● 匹配成功,创建原始对象(目标对象)的代理对象
4、获取bean执行方法
● 获取bean,调用方法并执行,完成操作
● 获取的bean是代理对象时,根据代理对象的运行模式运行原始方法与增强的内容,完成操作
直接打印对象看不出不一样,需要使用getClass打印,根据类型才能区分。
AOP核心概念:
目标对象(Target):原始功能去掉共性功能对应的类产生的对象,这种对象时无法直接完成最终工作的
代理(Proxy):目标对象无法直接完成工作,需要对其进行功能回填,通过原始对象的代理对象实现