1.AOP介绍
AOP(Aspect Oriented Programming)面向切面编程,一种编程范式,指导开发者如何组织程序结构,作用是在不改动原始设计的基础上为其进行功能增强
2.AOP的核心概念
概念 | 定义 | SpringAOP(注解开发)中的具体形式 |
---|---|---|
连接点(JoinPoint) | 程序执行过程中的任意位置,粒度为执行方法、抛出异常、设置变量等 | 执行方法 |
切入点(PointCut) | 匹配连接点的式子 | 一个切入点可以只描述一个方法,也可以匹配多个方法 |
通知(Advice) | 在切入点处执行的操作,也就是共性功能 | 以方法的形式呈现 |
切面(Aspect) | 描述通知与切入点的对应关系 | @Aspect 、@Before、@After、@Around、@AfterReturning、@AfterThrowing等注解 |
3.SpringAOP的使用步骤
(1)导入SpringAOP依赖坐标
注:spring-context中包含AOP相关依赖
<!--spring-context--><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>5.1.0.RELEASE</version></dependency><!--aspect--><dependency><groupId>org.aspectj</groupId><artifactId>aspectjweaver</artifactId><version>1.9.4</version></dependency>
(2)定义连接点
package com.example.service;public interface IUser {void eat();void sleep();
}
package com.example.service.impl;import com.example.service.IUser;
import org.springframework.stereotype.Service;@Service
public class UserImpl implements IUser {@Overridepublic void eat() {System.out.println("炫饭中... ...");}@Overridepublic void sleep() {System.out.println("深度睡眠中... ...");}
}
(3)定义通知类,制作通知
package com.example.aop;public class MyAdvice {public void advice(){System.out.println("在连接点之前执行的共性功能");}
}
(4)定义切入点
注:切入点定义依托一个不具有实际意义的方法进行,即无参数,无返回值,方法体无实际逻辑
package com.example.aop;import org.aspectj.lang.annotation.Pointcut;public class MyAdvice {@Pointcut("execution(void com.example.service.IUser.eat())")private void pt(){}public void advice(){System.out.println("在连接点之前执行的共性功能");}
}
(5)绑定切入点和通知关系,并指定通知添加到原始连接点的具体执行位置
package com.example.aop;import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;public class MyAdvice {@Pointcut("execution(void com.example.service.IUser.eat())")private void pt(){}@Before("pt()")public void advice(){System.out.println("在连接点之前执行的共性功能");}}
(6)定义通知类受Spring容器管理,并定义当前类为切面类
package com.example.aop;import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;@Component
@Aspect// 代表这个类是一个切面
public class MyAdvice {@Pointcut("execution(void com.example.service.IUser.eat())")private void pt(){}@Before("pt()")public void advice(){System.out.println("在连接点之前执行的共性功能");}
}
(7)开启Spring对AOP注解驱动支持
package com.example.config;import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;@Configuration
@ComponentScan("com.example")
@EnableAspectJAutoProxy// 开启Spring对AOP注解驱动支持
public class SpringConfig {
}
4.SpringAOP的工作流程
(1)Spring容器启动
(2)读取所有切面配置中的切入点
(3)初始化Bean,判定Bean对应的类中的方法是否匹配到任意切入点
- 匹配失败,创建对象
- 匹配成功,创建原始对象(目标对象)的代理对象
(4)获取Bean执行方法
- 获取Bean,调用方法并执行,完成操作(对应步骤(3)匹配失败的情况)
- 获取的Bean是代理对象时,根据代理对象的运行模式运行原始方法与增强的内容,完成操作(对应步骤(3)匹配成功的情况)